Java 代理
参考文章 http://haolloyin.blog.51cto.com/1177454/333257
代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问。代理需要代理类和被代理类有相同的对外接口。
1. 静态代理
abstract class Subject{ public abstract void request(); } class RealSubject extends Subject{ public void request() { System.out.println("This is real subject."); } } class Proxy extends Subject{ private Subject subject = null; public Proxy(Subject subject) { this.subject = subject; } public void request() { System.out.println("Proxy calls real subject."); subject.request(); } } public class StaticProxyTest { public static void main(String[] args) { Subject proxy = new Proxy(new RealSubject()); proxy.request(); } }
2. 动态代理
动态代理具有更强的灵活性,因为它不用在我们设计实现的时候就指定某一个代理类来代理哪一个被代理对象,我们可以把这种指定延迟到程序运行时由JVM来实现。态代理模式可以使得我们在不改变原来已有的代码结构的情况下,对原来的“真实方法”进行扩展、增强其功能,并且可以达到控制被代理对象的行为的目的。
JDK动态代理(基于接口的动态代理)
java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用代理对象关联的handler对象的Invoke方法来处理。
interface Subject{ // 被代理接口 public void request(); } class RealSubject implements Subject{ public void request() { System.out.println("This is real subject."); } } class JDKProxy implements InvocationHandler{ private Subject subject = null; public JDKProxy(Subject subject) { super(); this.subject = subject; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("ProxyHandler calls real subject."); return method.invoke(subject, args); } } public class JDKProxyTest { public static void main(String[] args) { Subject realSubject = new RealSubject(); InvocationHandler handler = new JDKProxy(realSubject); Subject proxySubject = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler); proxySubject.request(); } }
Cglib代理(基于类的动态代理)
cglib(Code Generation Library)是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。cglib封装了asm,可以在运行期动态生成新的class。 cglib用于AOP,jdk中的proxy必须基于接口,cglib却没有这个限制。
interface Subject{ // 被代理接口 public void request(); } class RealSubject implements Subject{ public void request() { System.out.println("This is real subject."); } } class CglibProxy implements MethodInterceptor { public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("CglibProxy calls real subject."); return methodProxy.invokeSuper(o, args); } } public class CglibProxyTest { public static void main(String[] args) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(RealSubject.class); enhancer.setCallback(new CglibProxy()); Subject subject = (Subject) enhancer.create(); subject.request(); } }
Spring AOP:
1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换