【Spring MVC系列】--(5)理解AOP

1、java反射

实用:JAVA反射机制及应用例子

http://407827531.iteye.com/blog/1173930

系统:java反射原理 

http://china-jianchen.iteye.com/blog/728774


JAVA 反射机制是Java 被视为动态(或准动态)语言的一个关键性质。
这个机制允许程序在运行时通过Reflection APIs 取得任何一个已知名称的class 的内部资讯
包括其modifiers(诸如public, private,static 等等)、superclass(例如Object)、interfaces(例如Cloneable)也包括fields 和methods 的所有资讯, 
并在运行时调用任意一个对象的方法;生成动态代理 

        String str = "com.xtlh.sinye.Goods"; 
//取得类  
        Class c = Class.forName(str);
//实例化对象     
        Object obj = c.newInstance();//初始化一个Goods的对象   
//取得方法(方法名,有类型)
        Method m = c.getMethod("setId",new Class[]{Class.forName("java.lang.String")});
	new Class[]{Class.forName("java.lang.String")}可以换为
	String.class;//更多类型 Long.TYPE Integer.TYPE,或者使用Long.class、Integer.class   
//取得方法(方法名,无类型)
	m = c.getMethod("getId",new Class[]{}); 	    
//执行带参函数
        m.invoke(obj,new Object[]{"it's apple"}); 
//执行不带参函数
	m.invoke(obj,new Object []{});     
//获得类中声明的方法   
        Method me[] = c.getDeclaredMethods();   
//判断是不是此类的对象(带参构造)
	boolean b1 = c.isInstance(new Integer(34)); 
//判断是不是此类的对象(无参构造)
	boolean b2 = c.isInstance(new Goods());
//取得类所有的方法继承来的方法等
	Method med1[] = c.getMethods();
//取得方法的参数类型   
	Class pvec[] = m.getParameterTypes();  
//方法的异常   
	Class evec[] = m.getExceptionTypes();   
//方法的返回类型   
	mee.getReturnType();  
//获得构造函数的参数类型    
	Class[] consParaType = cons.getParameterTypes();
//获取类的构造函数  
        Constructor ctorlist[] = c.getDeclaredConstructors(); 
//获取类的属性  
        Field fieldlist[] = c.getDeclaredFields(); 
//获取属性名称  
	field.getName()
//获取属性类型   
	field.getType()
//获取属性的修饰符 private/public/protected 
	int mod = field.getModifiers(); 
	Modifier.toString(mod)
//取得属性值
	Field fld = ccc.getDeclaredField("price");      
//改变属性的值  
	fld.setDouble(goods1, 25.0);  
//使用数组
	Class cla = Class.forName("java.lang.String");      
        Object arr = Array.newInstance(cla, 10);      
        Array.set(arr, 5, "hello Watermelon");      
        String s = (String) Array.get(arr, 5);   
//复杂数组使用
	int dims[] = new int[]{5, 10, 15};      
        Object array = Array.newInstance(Integer.TYPE, dims);      
        Object arrobj = Array.get(array, 3);      
        Class cl = arrobj.getClass().getComponentType();      
        System.out.println(cl);      
        arrobj = Array.get(arrobj, 5);      
        Array.setInt(arrobj, 10, 37);      
        int arrcast[][][] = (int[][][]) array;      
        System.out.println(arrcast[3][5][10]);  
//创建对象,根据指定的参数类型找到相应的构造函数并执行它,以创建一个新的对象实例。使用这种方法可以在程序运行时动态地创建对象,而不是在编译的时候创建对象,这一点非常有价值  
        Class clss = Class.forName("com.xtlh.sinye.Goods");      
        Class partypess[] = new Class[2];      
        partypess[0] = String.class;      
        partypess[1] = String.class;      
        Constructor ct = clss.getConstructor(partypess);      
        Object arglists[] = new Object[2];      
        arglists[0] = new String("hello");      
        arglists[1] = new String("orange");      
        Object retobjs = ct.newInstance(arglists); 
    


2、代理模式

2.1、静态代理:

设计模式之代理模式

http://www.blogjava.net/yangjunwei/archive/2013/04/23/398275.html
代理模式是一种间接调用的体现

就是执行代理类的方法,在代理类的方法中调用被代理类(委托类)的方法;

两个类实现同一个接口。


可以发现 每一个代理类只能为一个接口服务,这样一来程序开发中必然会产生过多的代理,而且,所有的代理操作除了调用的方法不一样之外,其他的操作都一样,则此时肯定是 重复代码。解决这一问题最好的做法是可以通过一个代理类完成全部的代理功能,那么此时就必须使用动态代理完成。 

2.2、动态代理:

java动态代理学习笔记

http://langyu.iteye.com/blog/410071 

委托的对象、接口和代理类都能动态改变;

1.interface InvocationHandler
Object invoke(Object proxy, Method method, Object[] args)
代理类继承之,并实现invoke。

2.class Proxy
在最后使用代理时出场。

Class<?> getProxyClass(ClassLoader loader, Class<?>[] interface)
用来产生代理类,参数要提供interface数组,它会生成这些interface的“虚拟实现”,
用来冒充真实的对象。

Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
产生代理对象,多了InvocationHandler参数(只是InvocationHandler接口的实现类),
它与代理对象关联,当请求分发到代理对象后,会自动执行h.invoke(...)方法,
invoke方法就是我们用来做N多事情的地方 -_-。 


关键是调用:

(1)委托类(B)实例

A/B b= new B();   

       代理类(C)实例(与委托类关联)
       C c = new C(b);   

(2)接口(A)对象(Proxy类实例)
        //这里把C与A新生成的代理类相关联   
        A a= (A) Proxy.newProxyInstance(b.getClass().getClassLoader(), b.getClass().getInterfaces(), c);   

(3)调用接口中方法       
        //这里无论访问哪个方法,都是会把请求转发到handler.invoke   
        a.print("All the test");   
        a.sayHello("Denny"); 

aop涉及 动态代理和反射

aop就是面向切面的编程。比如说你每做一次对数据库操作,都要生成一句日志。如果,你对数据库的操作有很多类,那你每一类中都要写关于日志的方法。但是如果你用aop,那么你可以写一个方法,在这个方法中有关于数据库操作的方法,每一次调用这个方法的时候,就加上生成日志的操作。

将程序中的交叉业务逻辑(比如安全,日志,事务等),封装成一个切面,然后注入到目标对象(具体业务逻辑)中去。


这里为什么代理只能代理接口,因为生成的代理类都继承自Proxy类,如果再继承其他类,跟JAVA继承(单继承)原则就有冲突


2.3、cglib实现类的代理:

java动态代理(JDK和cglib)

http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html

cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。


原文地址:https://www.cnblogs.com/pangblog/p/3341908.html