Spring AOP使用了两种代理机制:一种是基于JDK的动态代理;另一种是基于CGLib的动态代理
JDK动态代理只能提供对接口的代理,不能实现对类的代理
所以Spring AOP也采用了Cglib动态代理技术
下面采用实例分别叙述JDK动态代理和CGLib的区别
JDK动态代理:
1、
业务接口和实现类:
public interface BusinessService { void ink_print(); } public class BusinessServiceImpl implements BusinessService { @Override public void ink_print() { System.out.println("---------------业务主体----------------"); } }
JDK动态代理涉及到两个类Proxy和InvocationHandler
Proxy:生成业务实体对象,产生代理类
InvocationHandler:用来将横切代码和业务代码结合起来
2、
实现InvocationHanlder接口:
public class JdkHandler implements InvocationHandler { private Object target; public JdkHandler(Object target){ this.target = target; } /** * 将横切逻辑和业务方法结合在一起 * ①System.out.println("---------------拦截AOP----------------"); * ②System.out.println("---------------业务主体----------------"); */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //拦截从此展开 System.out.println("---------------拦截AOP----------------"); //业务主体代码,method.invoke是通过反射机制调用业务对象的方法 Object obj = method.invoke(target, args); return obj; } }
3、创建代理实例
public class TestJdkProxy { public static void main(String[] args) { BusinessService target = new BusinessServiceImpl(); JdkHandler handler = new JdkHandler(target); //根据target、handler产生代理实例 BusinessService proxy = (BusinessService) Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler); proxy.ink_print(); } }
调用主业务的方法体,然后通过Proxy产生代理类,最终由代理类去执行操作,这就是代理操作。
CGlib动态代理
CGLib采用非常底层的字节码技术,可以为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用
实现MethodInterceptor:创建动态代理类,将业务方法代码和横切逻辑代码组合
public class CglibProxy implements MethodInterceptor { private Enhancer enhancer = new Enhancer(); public Object getProxy(Class clazz){ enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object obj, Method arg1, Object[] arg2, MethodProxy proxy) throws Throwable { System.out.println("---------------拦截AOP----------------"); Object target = proxy.invokeSuper(obj, arg2); return target; } }
测试类: 此时就是和JDK动态代理不同,创建类代理,而不是接口
public class TestCglibProxy { public static void main(String[] args) { CglibProxy proxy = new CglibProxy(); BusinessServiceImpl businessService = (BusinessServiceImpl) proxy.getProxy(BusinessServiceImpl.class); businessService.ink_print(); } }