spring(二):后置处理器和AOP

2.后置处理器

2.1. BeanProcessor实现分析

  • bean – > wrappedBean 封装,设置一些参数
  • 处理器Bean:管理控制业务bean
  • 后置处理器的作用:判断bean实现了哪些接口,去实现那些接口中的逻辑
  • 注解都是实现了BeanPostProcessor接口 autowired --> AutowiredAnnotationBeanPostProcessor
  • 总结:Spring底层对BeanPostProcessor的使用, 包括bean的赋值, 注入其它组件, 生命周期注解功能等
  • 后置处理器起作用在创建对象、属性赋值之后

2.2 ApplicationContextAwareProcessor实现分析

说明关键代码
入口AnnotationConfigApplicationContext88 refresh();
BeanFactory初始化AbstractApplicationContext550 finishBeanFactoryInitialization(beanFactory);
AbstractApplicationContext869 beanFactory.preInstantiateSingletons();
获取实例DefaultListableBeanFactory769 getBean(beanName);
获取实例AbstractBeanFactory199 return doGetBean(name, null, null, false);
创建实例AbstractBeanFactory317 return createBean(beanName, mbd, args);
AbstractAutowireCapableBeanFactory501 Object beanInstance = doCreateBean(beanName, mbdToUse, args);
AbstractAutowireCapableBeanFactory541 instanceWrapper = createBeanInstance(beanName, mbd, args); 创建bean
578 populateBean(beanName, mbd, instanceWrapper); 属性赋值
AbstractAutowireCapableBeanFactory579 exposedObject = initializeBean(beanName, exposedObject, mbd); 初始化
将bean进行包装AbstractAutowireCapableBeanFactory1698 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
获取遍历后置处理器,将bean传给他,看bean实现哪些接口,要添加哪些业务逻辑AbstractAutowireCapableBeanFactoryObject current = beanProcessor.postProcessBeforeInitialization(result, beanName);
  • 需要遍历的后置处理器
    在这里插入图片描述

3.AOP

3.1 使用案例

  • AOP: 面向切面编程[底层就是动态代理]

    指程序在运行期间动态的将某段代码切入到指定方法位置进行运行的编程方式@EnableAspectJAutoProxy//配置类上打开aop开关

    • 通知方法:5种
      • 前置通知 logStart–@Before
      • 后置通知 logEnd – @After
      • 返回通知:logReturn --@AfterReturning
      • 异常通知:logEXception – @AfterThrowing
      • 环绕通知:动态代理,需手动执行joinPoint.proceed()方法 – @Around.
        • 在目标方法之前相当于前置通知、之后相当于后置通知
        • 比before还早,比@After早结束
public class Caculate {
	public int div(int i,int j) {	
		System.out.println("-----");
		return i/j;
	}
}


@Aspect
public class LogAspects {
	
	//@Before("execution(public int com.enjoy.cap10.aop.Caculate.div(int,int)")
	@Before("pointCut()")
	public void logBefore(JoinPoint joinPoint) {
		System.out.println(joinPoint.getSignature().getName()+"除法运行。。参数是{"+Arrays.asList(joinPoint.getArgs())+"}");
		
	}
	@After("pointCut()")
	public void logAfter() {
		System.out.println("除法运行。。结束");
	}
	@AfterReturning(value = "pointCut()",returning = "result")
	public void logReturn(Object result) {
		System.out.println("除法运行。。正常返回,结果是{"+result+"}");
	}
	@AfterThrowing(value = "pointCut()",throwing="xception")
	public void logException(Exception xception) {
		System.out.println("除法运行异常。。异常信息是{"+xception+"}");
	}
	
	@Around("pointCut()")
	public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
		System.out.println("@Arounb 执行目标方法之前");
		Object o = joinPoint.proceed();//最终是使用method.invoke 利用反射执行。
		System.out.println("@Around 执行目标方法结束");
		return o;
	}
	
	@Pointcut("execution(public int com.enjoy.cap10.aop.Caculate.*(..))")
	public void pointCut() {
		
	}
}

/*
   *  日志切面类的方法需要动态感知div方法运行
   * 通知方法:
 * 	前置通知 logStart--@Before
   *     后置通知  logEnd -- @After
   *     返回通知:logReturn --@AfterReturning
   *     异常通知:logEXception -- @AfterThrowing
   *     环绕通知:动态代理,需手动执行joinPoint.proceed()方法 -- @Around.在目标方法之前相当于前置通知、之后相当于后置通知
 */
@Configuration
@EnableAspectJAutoProxy//打开aop开关
public class Cap10MainConfig {

	@Bean
	public Caculate caculate() {
		return new Caculate();
	}
	
	@Bean
	public LogAspects logAspect() {
		return new LogAspects();
	}
}


public class Test10 {
	@Test
	public void test10() {
		AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap10MainConfig.class);
		Caculate bean = app.getBean(Caculate.class);
		int result = bean.div(4, 2);
		System.out.println(result);
		
		app.close();
	}
}

打印结果:
@Arounb 执行目标方法之前
div除法运行。。参数是{[4, 1]}
-----
@Around 执行目标方法结束
除法运行。。结束
除法运行。。正常返回,结果是{4}
4
  • 动态代理:–aop的动态代理对象,查看EnableAspectJAutoProxy注解
    • jdk:invocationHandler Proxy 通过反射实现,实现接口 --exposeProxy
    • CGLIB:继承要被动态代理(继承)–proxyTargetClass
  • @EnableAspectJAutoProxy核心注解
    • proxyTargetClass():控制aop的具体实现方式,true 表示使用cglib,false表示使用java的Proxy,默认为false
    • exposeProxy():控制代理的暴露方式,true使用ThreadLocal的方式(主要是线程安全问题),默认为false

3.2 源码分析

  • AnnotationAwareAspectJAutoProxyCreator.class 贯穿了AOP功能
    • 父类 AspectJAwareAdvisorAutoProxyCreator
      • 父类:AbstractAdvisorAutoProxyCreator
        • 父类 AbstractAutoProxyCreator
          • 父类 extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
    • BeanFactoryAware 能把beanFactory传进来
    • SmartInstantiationAwareBeanPostProcessor:实例化Creator时使用的后置处理器;关注后置处理器–在bean初始化前后做的事情,如何自定装配beanFactory
    • ProxyProcessorSupport:实现order接口–方便排序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7UYmtMMH-1584868094872)(2.spring-1.assets/1584289722136.png)]

  • 关注:AnnotationAwareAspectJAutoProxyCreator 怎么创建
    • 默认的beanID是AUTO_PROXY_CREATOR_BEAN_NAME =“org.springframework.aop.config.internalAutoProxyCreator”; 在AopConfigUtils里,
    • 比普通bean创建的时机要早,创建流程大部分相似。
    • 根据反射创建bean BeanUtils.instantiateClass()
    • 开始创建的时候声明一个名字
  • InstantiationAwareBeanPostProcessor: 前后置处理器
  • aop就是利用前后置处理器进行切面处理。单例加强。
  • createBean方法: Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
    • Object bean = resolveBeforeInstantiation(beanName, mbdToUse); 跟进去
      • bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
      • bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
  • aop对象都是使用动态代理创建出来的对象,用jdk反射或者cglib实现。
  • 前置是拿到方法,后置是真正创建实例、返回bean–代理对象和增强器关联起来

核心类加载

  • AOP核心其实就是创建AnnotationAwareAspectJAutoProxyCreator类(后置处理器),该类最终实现的接口为BeanPostProcessor类,
  • 创建好后置处理器的对象,放在容器中,其实所有注解都有对应自己的后置处理器其它bean组件的创建对象的时候,都会会被AnnotationAwareAspectJAutoProxyCreator的后置处理器拦截,拦截到创建过程。
  1. 传入配置类@Configuration创建IOC容器,进入spring启动类 AnnotationConfigApplicationContext
  2. 进入refresh方法,注册bean后置处理器 registerBeanPostProcessors(beanFactory);
  3. 查看方法:PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
    1. 188行:先获取ioc容器已经定义了的需要创建对象的所有BeanPostProcessor,
    2. 195行:给容器中加别的beanPostProcessor beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
    3. 220行,优先级排序 。spring机制:优先级排序优先注册实现了PriorityOrdered接口的BeanPostProcessor;//哪些实现PriorityOrdered接口的BeanPostProcessor接口优先注册,还做了些处理,判断是不是实现了PriorityOrdered接口,不同类型保存在不同的
    4. 224行:再给容器中注册实现了Ordered接口的BeanPostProcessor;
    5. 236行:注册没实现优先级接口的BeanPostProcessor;
    6. 226行:创建bean实例的方法。BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);当beanName为org.springframework.aop.config.internalAutoProxyCreator时跟进去
  4. 进到 AbstractBeanFactory.doGetBean方法
    1. 314行:不存现先创建单例 mbd.isSingleton()
      1. 进入AbstractAutowireCapableBeanFactory.createBean方法
        1. 490行。进行初始化的前置处理和后置处理 Object bean = resolveBeforeInstantiation(beanName, mbdToUse);因为bean没有创建完成实际上返回的是null/false
        2. 501 行。创建实例。Object beanInstance = doCreateBean(beanName, mbdToUse, args);跟进去
        3. Bean的创建流程:在AbstractAutowireCapableBeanFactory类
          1. 在541行,创建bean的实例;创建我们的AbstractAutowireCapableBeanFactory实例 instanceWrapper = createBeanInstance(beanName, mbd, args);
          2. 在578行,populateBean()给bean的各种属性赋值 populateBean(beanName, mbd, instanceWrapper);
          3. 在579行,initializeBean()初始化bean, initializeBean(beanName, exposedObject, mbd);
  5. 初始化的过程分2步。
    1. 1688行 判断bean是否实现Aware接口 invokeAwareMethods(beanName, bean);
      1. 1728行 进入设置工厂的方法 ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
      2. 进入AbstractAdvisorAutoProxyCreator.setBeanFactory() ,进入63行 initBeanFactory初始化
      3. 79行进入类AnnotationAwareAspectJAutoProxyCreator的initBeanFactory()方法,调到了AnnotationAwareAspectJAutoProxyCreator给容器中创建自动代理器的,做了以下2件事
        1. 82行:创建了ReflectiveAspectJAdvisorFactory反射机制,相当于把aspectJAdvisorFactory对象通知工厂
        2. 85行:new BeanFactoryAspectJAdvisorsBuilderAdapter,通知适配器其实相当于aspectJAdvisorFactory通知到构建器的适配器, 把aspectJAdvisorFactory重新包装了一下
    2. 在1698行,wrappedBean =applyBeanPostProcessorsBeforeInitialization(),调用这个后,返回一个被包装后的bean, 也就是bean后置处理器调用,点击进入
      1. 417行:AbstractAutowireCapableBeanFactory类applyBeanPostProcessorsBeforeInitialization()具体处理方法在422行后置处理器
    3. 在AbstractAutowireCapableBeanFactory类1702行:执行初始化自定义方法invokeInitMethods(beanName, wrappedBean, mbd).
      1. 其实就是声明@Bean注解的时候,指定初始化方法或销毁方法是什么,在这里执行
    4. 在AbstractAutowireCapableBeanFactory类1710行:执行后置处理器方法:wrappedBean =applyBeanPostProcessorsAfterInitialization
  6. BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功
  7. 回到PostProcessorRegistrationDelegate类当BeanPostProcessor创建成功后,186行registerBeanPostProcessors()
    1. 看 248行registerBeanPostProcessors(beanFactory,internalPostProcessors), 点进去,
    2. 将创建成功的BeanPostProcessor对象加入工厂,AOP核心对象创建完成

源码跟踪图

在这里插入图片描述

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值