最近因为项目需要温习Spring的时候,看到有一章节讲的是JDK代理调用,所以就结合公司的Invoke代理调用再一次看了一遍代理这一块。
一、反射
通常java中都是由java类编译成class文件,即先有类再有对象,那么有了对象之后我们就可以调用对象的方法和属性。但是通过反射我们可以通过Class对象来调用类里面的方法。通过反射可以调用私有方法和私有属性。大部分框架都是运用反射原理。
这是获取class对象的三种方式
//1、通过对象调用 getClass() 方法来获取,通常应用在:比如你传过来一个 Object
// 类型的对象,而我不知道你具体是什么类,用这种方法
Person p1 = new Person();
Class c1 = p1.getClass();
//2、直接通过 类名.class 的方式得到,该方法最为安全可靠,程序性能更高
// 这说明任何一个类都有一个隐含的静态成员变量 class
Class c2 = Person.class;
//3、通过 Class 对象的 forName() 静态方法来获取,用的最多,
// 但可能抛出 ClassNotFoundException 异常
Class c3 = Class.forName("com.ys.reflex.Person");
二、动态代理
关于动态代理和静态代理 当一个对象(客户端)不能或者不想直接引用另一个对象(目标对象),这时可以应用代理模式在这两者之间构建一个桥梁--代理对象。 按照代理对象的创建时期不同,可以分为两种: 静态代理:事先写好代理对象类,在程序发布前就已经存在了; 动态代理:应用程序发布后,通过动态创建代理对象。
动态代理:应用程序发布后,通过动态创建代理对象。
三、JDK动态代理
JDK动态代理只能针对实现了接口的类生成代理。
public Object newProxy(Object targetObject) {// 将目标对象传入进行代理
this.targetObject = targetObject; <br> //注意这个方法的参数,后面是实现类实现的接口
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(), this);// 返回代理对象
在上面的代码中,我们知道,jdk传入的其实是实现类所实现的接口
targetObject.getClass().getInterfaces(), 所以jdk动态代理只能对接口Interface进行代理。
四、动态代理的应用
动态代理还有一种是Cglib,是实现不是接口的类的动态代理。
AOP(Aspect-OrientedProgramming,面向切面编程),AOP包括切面(aspect)、通知(advice)、连接点(joinpoint),实现方式就是通过对目标对象的代理在连接点前后加入通知,完成统一的切面操作。
实现AOP的技术,主要分为两大类:
一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;
二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。
Spring提供了两种方式来生成代理对象: JDKProxy和Cglib,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。
默认的策略是如果目标类是接口,则使用JDK动态代理技术,如果目标对象没有实现接口,则默认会采用CGLIB代理。
如果目标对象实现了接口,可以强制使用CGLIB实现代理(添加CGLIB库,并在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>)。