本文共 2837 字,大约阅读时间需要 9 分钟。
目录
首先我们来看一些概念性的描述:
注解(Annotation):也叫元数据。一种代码级别的说明。它是JDK 1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
反射:赋予程序在运行时自省(introspect)的能力。指的是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性。
静态代理:事先写好代理类,缺点是每个业务类都要对应一个代理类,非常不灵活。
动态代理:运行时自动生成代理对象,是一种方便运行时动态处理代理方法调用的机制。很多场景都是利用类似机制,比如:用来包装RPC调用、面向切面编程(AOP)。通过代理可以让调用者和实现者之间解耦。
JDK动态代理:代理类需要实现JDK的 InvocationHandler 接口 ,其中 完成真实方法的调用是通过 invoke 方法来实现的。必须实现了接口的类才能用这种办法生成代理对象,依赖接口。
cglib动态代理:通过生成类的子类作为代理类,对于接口的依赖被克服了。
AOP:面向切面编程。在不影响原有功能的情况下,对程序进行横向扩展。说说我自己的理解吧。某个类的方法已经封装好了,现在我们要对原有的方法进行干预,但是又不能破坏原来的类,这时候就需要aop的思想,把这个切点扩展成一个面来进行操作。(也就是生成该类的代理,对代理进行操作)
依赖注入(控制反转):Spring是通过反射来实现依赖注入的。什么是依赖呢? 如果在A类里面调用B类,那么A类需要依赖于B类,通常的话,是A类来创建B类的示例。但是spring 里面,创建的动作由spring容器来完成,然在在运行的时候注入到A类中,所以叫做依赖注入。比如说注解@Resource和@Autowired等
总结: 反射和动态代理都是运行时的机制。通过反射,我们可以在运行时操作类或者对象。而动态代理,它是一个代理机制,代理可以看做是对调用目标的一个包装,代理除了可以调用目标,还可以做一些其他的操作。通过代理可以让调用者与实现者解耦。动态代理是运行的时候才自动生成代理对象,如果是编码阶段显式的指定代理类,就是静态代理了。
通过代理可以让调用者和实现者之间解耦。
JDK的动态代理:通常代理类需要实现JDK的 InvocationHandler 接口 ,其中 完成真实方法的调用是通过 invoke 方法来实现的。通过InvocationHandler接口,所有方法都由该Handler来进行处理,即所有被代理的方法都由InvocationHandler接管实际的处理任务。此外,我们常可以在invoke方法实现中增加自定义的逻辑实现,实现对被代理类的业务逻辑无侵入。
public class DynamicProxy { public static void main(String[] args) { HelloImpl hello = new HelloImpl(); //实现对应的InvocationHandler MyInvocationHandler handler = new MyInvocationHandler(hello); // 构造代码实例 Hello proxyHello = (Hello) Proxy.newProxyInstance(HelloImpl.class.getClassLoader(), HelloImpl.class.getInterfaces(), handler); // 调用代理方法 proxyHello.sayHello(); }} interface Hello { void sayHello(); } class HelloImpl implements Hello { @Override public void sayHello() { System.out.println("Hello World"); } } class MyInvocationHandler implements InvocationHandler { private Object target; public MyInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Invoking sayHello"); Object result = method.invoke(target, args); return result; } }
JDK proxy 的动态代理,其实现过程可以简化为:
JDK proxy 的方法,有接口的依赖,那如果被调用者没有实现接口,而我们还希望利用动态代理机制,怎么办?
我们知道,Spring AOP 支持两种方式的动态代理,JDK proxy 和 cglib,如果我们选择cglib方式,cglib 是通过 asm 直接操作字节码,所以可以不实现接口。cglib 动态代理采用的是创建目标类的子类的方式,因为是子类,可以达到近似使用被调用者本身的效果。
通过代理静默的解决一些业务无关的问题,比如:安全、事务、日志、资源关闭,让开发者可以只关心于他的业务。
以上,有点晦涩。有时间再补充扩展吧。?
转载地址:http://znlgi.baihongyu.com/