五、Spring AOP(续)
53. 什么情况下AOP会失效,怎么解决?
1. 失效原因
- 方法是private也会失效,解决:改成public
- 目标类没有配置为Bean也会失效, 解决:配置为Bean,因为SpringAOP只会为Bean创建动态代理
- 切点表达式没有配置正确
- 内部调用不会触发AOP(cglib本可以)
2. 内部调用不会触发AOP
- 在本类中自动注入当前的bean
@Service
//@Lazy //懒加载,除非注入使用了,才会被spring托管 默认eager,即不需要注入就加载
//@Scope("prototype") singleton默认单例
public class StudentBizImpl implements StudentBiz{
//如果发现实现了AOP,就会创建动态代理,Spring容器中就只会有代理对象了,注入的也是动态代理对象
@Autowired
private StudentBiz studentBiz;
public int add(String name){
System.out.println("============业务层==============");
System.out.println("用户名是否重名");
int result=studentDao.add(name);
studentBiz.update(name);
System.out.println("============业务层操作结束2==========");
return result;
}
- 设置暴露当前代理对象到本地线程, 可以通过AopContext.currentProxy() 拿到当前正在调用的动态代理对象
@EnableAspectJAutoProxy(exposeProxy = true)
AopContext.currentProxy() 拿到当前正在调用的动态代理对象
public int mod(int numA,int numB){
System.out.println("执行目标方法:mod");
//获取当前线程的动态代理对象,防止调用本类的方法,不会进行增强(cglib本身就实现了,这个主要用于JDK)
int retVal=((Caculate)AopContext.currentProxy()).add(numA,numB);
int retVal=this.add(numA,numB);
return retVal%numA;
}
54.Spring的AOP是在哪里创建的动态代理?
- 正常的Bean会在Bean的生命周期的初始化后, 通过BeanPostProcessor.postProcessAfterInitialization创建aop的动态代理
- 还有一种特殊情况: 循环依赖的Bean会在Bean的生命周期属性注入时存在的循环依赖的情况下, 也会为循环依赖的Bean通过MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition创建aop
55. Spring的 Aop的完整实现流程?
Aop的实现大致分为三大步:JavaConfig
当@EnableAspectJAutoProxy 会通过@Import注册一个BeanPostProcessor处理AOP
- 解析切面: 在Bean创建之前的第一个Bean后置处理器会去解析切面(解析切面中通知、切点,一个通知就会解析成一
个advisor(通知、切点)) - 创建动态代理:正常的Bean初始化后调用BeanPostProcessor,拿到之前缓存的advisor ,再通过advisor中pointcut
判断当前Bean是否被切点表达式匹配,如果匹配,就会为Bean创建动态代理(创建方式1.jdk动态代理2.cglib)。 - 调用:拿到动态代理对象, 调用方法就会判断当前方法是否增强的方法,如果是就会通过调用链的方式依次去执行通知