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();
}
}