Spring AOP有两种动态代理的方式,一种是jdk的动态代理,一种是cglib实现的动态代理,看下两种代理的实现方式。
1.jdk的动态代理
接口:
public interface ISaler {
public void buy();
}
实现类:
public class CPU implements ISaler{
@Override
public void buy() {
System.out.println("buy cpu");
}
}
代理类:
public class DynamicsAgent implements InvocationHandler {
//被代理对象
private Object obj;
public DynamicsAgent(Object obj) {
this.obj = obj;
}
//此方法产生一个对象,这个对象可以用来代理被代理的对象,即获取代理对象
public Object getProxy(){
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
before();
//执行被代理对象的method方法
Object o = method.invoke(obj, args);
after();
return o;
}
public void before(){
System.out.println("-----brfore---------");
}
public void after(){
System.out.println("-----after---------");
}
}
测试类:
public class Test {
public static void main(String[] args) {
CPU cpu = new CPU();
DynamicsAgent da = new DynamicsAgent(cpu);
//生成一个代理对象,用被代理对象的接口表示
ISaler p = (ISaler)da.getProxy();
//实际是执行代理类的invoke方法
p.buy();
}
}
执行结果:
-----brfore---------
buy cpu
-----after---------
2.cglib实现:
实现类同上,可以去掉接口:
public class CPU implements ISaler{
@Override
public void buy() {
System.out.println("buy cpu");
}
}
代理类:
public class CGLibProxy implements MethodInterceptor {
//被代理对象
private Object obj;
public CGLibProxy(Object obj) {
this.obj = obj;
}
//此方法产生一个对象,这个对象可以用来代理被代理的对象,即获取代理对象
public Object getProxy(){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(obj.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy mp) throws Throwable {
before();
Object o = mp.invoke(obj, args);
after();
return o;
}
public void before(){
System.out.println("-----brfore---------");
}
public void after(){
System.out.println("-----after---------");
}
}
测试类:
public class Test {
public static void main(String[] args) {
CPU c = new CPU();
CGLibProxy cp = new CGLibProxy(c);
CPU p = (CPU)cp.getProxy();
//实际是执行代理类的intercept方法
p.buy();
}
}
执行结果:
-----brfore---------
buy cpu
-----after---------
两种方式的比较:
采用jdk方式来实现动态代理则需要目标类必须实现接口。
采用cglib方式来实现动态类则目标类不能为final类型。
cglib的执行效率更高,但是需要导入第三方包。