一、如何理解代理技术
Proxy:不用你去做,别人代替你去处理。如Windows快捷方式,又如房屋中介
起到一个中介作用,通过代理对象,可以去掉客户不能看到的内容和服务或者添加客户需要的额外服务。
二、代理模式
代理模式使用代理对象完成用户请求,屏蔽用户对真实对象的访问。现实世界的代理人被授权执行当事人的一些事宜,无需当事人出面,从第三方的角度看,似乎当事人并不存在,因为他只和代理人通信。
而事实上代理人是要有当事人的授权,并且在核心问题上还需要请示当事人。
在软件设计中,使用代理模式的意图也很多,比如因为安全原因需要屏蔽客户端直接访问真实对象,或者在远程调用中需要使用代理类处理远程方法调用的技术细节 (如 RMI),
也可能为了提升系统性能,对真实对象进行封装,从而达到延迟加载的目的。
代理模式角色分为 4 种:
1.主题接口:定义代理类和真实主题的公共对外方法,也是代理类代理真实主题的方法;
2.真实主题:真正实现业务逻辑的类;
3.代理类:用来代理和封装真实主题;
4.Main:客户端,使用代理类和主题接口完成一些工作。
三、具体使用
1.静态代理

/** * Created by solverpeng on 2016/6/29. */ public interface Factory { void say(); void produce(); }

/** * NikeFatory * * @author solverpeng * @create 2016-06-29-11:28 */ public class NikeFactory implements Factory { @Override public void say() { System.out.println("我要开始生产了!"); } @Override public void produce() { System.out.println("正在生产Nike衣服!"); } }

/** * NikeFactoryProxy * * @author solverpeng * @create 2016-06-29-11:30 */ public class NikeFactoryProxy implements Factory { private NikeFactory nikeFactory; public NikeFactoryProxy() { this.nikeFactory = new NikeFactory(); } @Override public void say() { before(); nikeFactory.say(); after(); } @Override public void produce() { before(); nikeFactory.produce(); after(); } private void after() { System.out.println("大家做的不错!"); } private void before() { System.out.println("在正式开始生产之前,我要说两句!"); } }

@Test public void testStaticProxy() { NikeFactoryProxy nikeFactoryProxy = new NikeFactoryProxy(); nikeFactoryProxy.say(); nikeFactoryProxy.produce(); }
2.JDK动态代理

@Test public void testJDKProxy() { Factory proxyInstance = (Factory) Proxy.newProxyInstance(NikeFactory.class.getClassLoader(), NikeFactory.class.getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(NikeFactory.class.newInstance(), args); } }); proxyInstance.say(); proxyInstance.produce(); }

/** * 通用的代理生产工厂 * * @author solverpeng * @create 2016-06-29-11:45 */ public class DynamicProxy implements InvocationHandler { private Object target; public DynamicProxy(Object target) { this.target = target; } @SuppressWarnings("unchecked") public <T> T getProxy() { return (T)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(target, args); } }

@Test public void testJDKProxy2() { DynamicProxy dynamicProxy = new DynamicProxy(new NikeFactory()); Factory proxy = dynamicProxy.getProxy(); proxy.say(); proxy.produce(); }
3.CGLIB动态代理(需要额外导入cglib包)

/** * CglibProxy * * @author solverpeng * @create 2016-06-29-14:40 */ public class CglibProxy implements MethodInterceptor{ private static CglibProxy instance = new CglibProxy(); public CglibProxy() { } public static CglibProxy getInstance() { return instance; } @SuppressWarnings("unchecked") public <T> T getProxy(Class<T> cls) { return (T)Enhancer.create(cls, this); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { return methodProxy.invokeSuper(o, objects); } }

@Test public void testCglibProxy2() { NikeFactory proxy = CglibProxy.getInstance().getProxy(NikeFactory.class); proxy.say(); proxy.produce(); }
四、总结
JDK动态代理获取代理的是通过:Proxy.newProxyInstance() 方法来获取的,需要一个 InvocationHandler 类型的对象。传入的参数为目标对象。
CGLIB 动态代理获取代理是通过:Enhancer.create() 方法,需要一个 MethodInterceptor 类型的对象。
在使用 CGLIB 包的时候,可能会出现 java.lang.ClassNotFoundException: org.objectweb.asm.Type 的异常,导入 spring 下的 cglib 包就ok。