Spring全家桶面试题(一)之Spring Framework(七)

五、Spring AOP(续)

53. 什么情况下AOP会失效,怎么解决?

1. 失效原因

  1. 方法是private也会失效,解决:改成public
  2. 目标类没有配置为Bean也会失效, 解决:配置为Bean,因为SpringAOP只会为Bean创建动态代理
  3. 切点表达式没有配置正确
  4. 内部调用不会触发AOP(cglib本可以)

2. 内部调用不会触发AOP

  1. 在本类中自动注入当前的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;
   }
  1. 设置暴露当前代理对象到本地线程, 可以通过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是在哪里创建的动态代理?

  1. 正常的Bean会在Bean的生命周期的初始化后, 通过BeanPostProcessor.postProcessAfterInitialization创建aop的动态代理
  2. 还有一种特殊情况: 循环依赖的Bean会在Bean的生命周期属性注入时存在的循环依赖的情况下, 也会为循环依赖的Bean通过MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition创建aop

55. Spring的 Aop的完整实现流程?

Aop的实现大致分为三大步:JavaConfig
当@EnableAspectJAutoProxy 会通过@Import注册一个BeanPostProcessor处理AOP

  1. 解析切面: 在Bean创建之前的第一个Bean后置处理器会去解析切面(解析切面中通知、切点,一个通知就会解析成一
    个advisor(通知、切点))
  2. 创建动态代理:正常的Bean初始化后调用BeanPostProcessor,拿到之前缓存的advisor ,再通过advisor中pointcut
    判断当前Bean是否被切点表达式匹配,如果匹配,就会为Bean创建动态代理(创建方式1.jdk动态代理2.cglib)。
  3. 调用:拿到动态代理对象, 调用方法就会判断当前方法是否增强的方法,如果是就会通过调用链的方式依次去执行通知

你可能感兴趣的:(后端,#,面试笔试,spring,java,后端)