JDK动静代理
jdk动静代理是利用反射机制生成一个实现代理接口的匿名类,在调用业务办法前调用InvocationHandler解决。代理类必须实现InvocationHandler接口,并且,JDK动静代理只能代理实现了接口的类,没有实现接口的类是不能实现JDK动静代理。
应用JDK动静代理类根本步骤:
1、须要被代理的类和接口
public interface OrderService { public void save(UUID orderId, String name);}public class OrderServiceImpl implements OrderService { @Override public void save(UUID orderId, String name) { System.out.println("call save()办法,save:" + name); }}
2、代理类,须要实现InvocationHandler接口,重写invoke办法
public class JDKProxy implements InvocationHandler { //须要代理的指标对象 private Object targetObject; public Object createProxyInstance(Object targetObject) { this.targetObject = targetObject; return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(), this.targetObject.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //被代理对象 OrderServiceImpl bean = (OrderServiceImpl) this.targetObject; Object result = null; //切面逻辑(advise),此处是在指标类代码执行之前 System.out.println("---before invoke----"); if (bean.getUser() != null) { result = method.invoke(targetObject, args); } System.out.println("---after invoke----"); return result; }}
3、应用Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)动态创建代理类对象,通过代理类对象调用业务办法。
public class AOPTest { public static void main(String[] args) { JDKProxy factory = new JDKProxy(); //Proxy为InvocationHandler实现类动态创建一个合乎某一接口的代理实例 OrderService orderService = (OrderService) factory.createProxyInstance(new OrderServiceImpl("JDK")); //由动静生成的代理对象来orderService 代理执行程序 orderService.save(UUID.randomUUID(), "aoho"); }}---before invoke----call save()办法,save:JDK---after invoke----
Cglib动静代理
cglib是针对类来实现代理的,它会对指标类产生一个代理子类,通过办法拦挡技术对过滤父类的办法调用。代理子类须要实现MethodInterceptor接口
1.被代理类,该类能够实现接口,也能够不实现接口
public class OrderManager { public void save(UUID orderId, String name) { System.out.println("call save()办法,save:" + name); }}
2.代理类,实现MethodInterceptor接口,重写intercept办法
public class CGLibProxy implements MethodInterceptor { // CGLib须要代理的指标对象 private Object targetObject; public Object createProxyObject(Object obj) { this.targetObject = obj; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(obj.getClass()); //回调办法的参数为代理类对象CglibProxy,最初加强指标类调用的是代理类对象CglibProxy中的intercept办法 enhancer.setCallback(this); //加强后的指标类 Object proxyObj = enhancer.create(); // 返回代理对象 return proxyObj; } @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object obj = null; //切面逻辑(advise),此处是在指标类代码执行之前 System.out.println("---before intercept----"); obj = method.invoke(targetObject, args); System.out.println("---after intercept----"); return obj; }}
3.创立代理类对象,通过代理类对象调用业务办法
public class AOPTest { public static void main(String[] args) { OrderManager order = (OrderManager) new CGLibProxy().createProxyObject(new OrderManager("aoho")); order.save(UUID.randomUUID(), "CGLIB"); } ---before invoke----call save()办法,save:CGLIB---after invoke----
JDK与Cglib动静代理比照?
1、JDK动静代理只能代理实现了接口的类,没有实现接口的类不能实现JDK的动静代理;
2、Cglib动静代理是针对类实现代理的,运行时动静生成被代理类的子类拦挡父类办法调用,因而不能代理申明为final类型的类和办法;
Spring如何抉择两种代理模式的?
1、如果指标对象实现了接口,则默认采纳JDK动静代理;
2、如果指标对象没有实现接口,则应用Cglib代理;
3、如果指标对象实现了接口,但强制应用了Cglib,则应用Cglib进行代理
咱们能够联合源码来看下,下面的抉择:
参考:
深刻了解Spring AOP的动静代理