1.首先区别一下Spring的动态代理和Spring AOP
2.spring 动态代理ProxyFactory其实封装了 CGLIB和JDK,他会自动判断用那种动态代理,所以开发过程中可以直接使用Spring的动态代理会更加方便。
4.这里说明一下CGLIB是一个单独的项目,Spring是把CGLIB的源码copy了一份到Spring中,并非依赖CGLIB的项目(jar 包),从而避免CGLIB升级影响Spring。
5.
//目标对象或者被代理对象
UserService target =new UserService();
ProxyFactory proxyFactory =new ProxyFactory();
//设置目标对象
proxyFactory.setTarget(target);
//这里如果设置interface就是使用JDK 动态代理。
//proxyFactory.setInterfaces(target.getClass().getInterfaces());
//设置通知Advice这里有很多Advice - before after around return..
proxyFactory.addAdvice(new MethodBeforeAdvice() {
@Override
public void before(Method method,Object[] args,Object target)throws Throwable {
//这里和我们写的JDK CGLIB不一样,会在执行before后自动去执行目标对象的方法,不需要通过metod.invoke(targe,args)
System.out.println("before");
}
});
proxyFactory.addAdvice(new AfterReturningAdvice() {
@Override
public void afterReturning(Object returnValue,Method method,Object[] args,Object target)throws Throwable {
System.out.println("after returning");
}
});
//around
proxyFactory.addAdvice(new MethodInterceptor() {
@Nullable
@Override
public Object invoke(@NotNull MethodInvocation invocation)throws Throwable {
System.out.println("around before");
Object proceed = invocation.proceed();//around非常特殊,他的这个是MethodInterceptor,调用proceed是让他继续执行其他的advice
System.out.println("around after");
return proceed;
}
});
//如果是JDK动态代理这里就会报错,因为生成的代理对象是接口对应的子类对象和UserService没关系
UserService proxy = (UserService)proxyFactory.getProxy();
proxy.test();
4.proxyFactory.addAdvice()可以添加多个按顺序执行 - 看上面代码,最终的执行结果
before - around before - test - around after - after returning
注:before和around before的执行顺序取决于advice加入的顺序
5.类似于CGLib,Spring动态代理也可以指定切方法 Advisor = Adivce + PointCut
所以Advisor可以指定哪个Adivce应用在哪个方法上
proxyFactory.addAdvisor(new PointcutAdvisor() {
@Override
public Pointcut getPointcut() {
//指定匹配类型
return new StaticMethodMatcherPointcut() {
@Override
public boolean matches(Method method,Class targetClass) {
return method.getName().equals("test");
}
};
}
@Override
public Advice getAdvice() {
//指定Advice,这里就不写了。
return null;
}
});