12. 把AOP拓展到Bean的生命周期
12. 把AOP拓展到Bean的生命周期
工程结构
lqf-spring-step-12
├── main
│ ├── java
│ │ └── lqf
│ │ └── springframework
│ │ ├── aop
│ │ │ ├── AdvisedSupport.java
│ │ │ ├── Advisor.java
│ │ │ ├── BeforeAdvice.java
│ │ │ ├── ClassFilter.java
│ │ │ ├── MethodBeforeAdvice.java
│ │ │ ├── MethodMatcher.java
│ │ │ ├── Pointcut.java
│ │ │ ├── PointcutAdvisor.java
│ │ │ ├── TargetSource.java
│ │ │ ├── aspectj
│ │ │ │ ├── AspectJExpressionPointcut.java
│ │ │ │ └── AspectJExpressionPointcutAdvisor.java
│ │ │ └── framework
│ │ │ ├── AopProxy.java
│ │ │ ├── Cglib2AopProxy.java
│ │ │ ├── JdkDynamicAopProxy.java
│ │ │ ├── ProxyFactory.java
│ │ │ ├── ReflectiveMethodInvocation.java
│ │ │ ├── adapter
│ │ │ │ └── MethodBeforeAdviceInterceptor.java
│ │ │ └── autoproxy
│ │ │ └── DefaultAdvisorAutoProxyCreator.java
│ │ ├── beans
│ │ │ ├── BeansException.java
│ │ │ ├── PropertyValue.java
│ │ │ ├── PropertyValues.java
│ │ │ └── factory
│ │ │ ├── Aware.java
│ │ │ ├── BeanClassLoaderAware.java
│ │ │ ├── BeanFactory.java
│ │ │ ├── BeanFactoryAware.java
│ │ │ ├── BeanNameAware.java
│ │ │ ├── ConfigurableListableBeanFactory.java
│ │ │ ├── DisposableBean.java
│ │ │ ├── FactoryBean.java
│ │ │ ├── HierarchicalBeanFactory.java
│ │ │ ├── InitializingBean.java
│ │ │ ├── ListableBeanFactory.java
│ │ │ ├── config
│ │ │ │ ├── AutowireCapableBeanFactory.java
│ │ │ │ ├── BeanDefinition.java
│ │ │ │ ├── BeanFactoryPostProcessor.java
│ │ │ │ ├── BeanPostProcessor.java
│ │ │ │ ├── BeanReference.java
│ │ │ │ ├── ConfigurableBeanFactory.java
│ │ │ │ ├── InstantiationAwareBeanPostProcessor.java
│ │ │ │ └── SingletonBeanRegistry.java
│ │ │ ├── support
│ │ │ │ ├── AbstractAutowireCapableBeanFactory.java
│ │ │ │ ├── AbstractBeanDefinitionReader.java
│ │ │ │ ├── AbstractBeanFactory.java
│ │ │ │ ├── BeanDefinitionReader.java
│ │ │ │ ├── BeanDefinitionRegistry.java
│ │ │ │ ├── CglibSubclassingInstantiationStrategy.java
│ │ │ │ ├── DefaultListableBeanFactory.java
│ │ │ │ ├── DefaultSingletonBeanRegistry.java
│ │ │ │ ├── DisposableBeanAdapter.java
│ │ │ │ ├── FactoryBeanRegistrySupport.java
│ │ │ │ ├── InstantiationStrategy.java
│ │ │ │ └── SimpleInstantiationStrategy.java
│ │ │ └── xml
│ │ │ └── XmlBeanDefinitionReader.java
│ │ ├── context
│ │ │ ├── ApplicationContext.java
│ │ │ ├── ApplicationContextAware.java
│ │ │ ├── ApplicationEvent.java
│ │ │ ├── ApplicationEventPublisher.java
│ │ │ ├── ApplicationListener.java
│ │ │ ├── ConfigurableApplicationContext.java
│ │ │ ├── event
│ │ │ │ ├── AbstractApplicationEventMulticaster.java
│ │ │ │ ├── ApplicationContextEvent.java
│ │ │ │ ├── ApplicationEventMulticaster.java
│ │ │ │ ├── ContextClosedEvent.java
│ │ │ │ ├── ContextRefreshedEvent.java
│ │ │ │ └── SimpleApplicationEventMulticaster.java
│ │ │ └── support
│ │ │ ├── AbstractApplicationContext.java
│ │ │ ├── AbstractRefreshableApplicationContext.java
│ │ │ ├── AbstractXmlApplicationContext.java
│ │ │ ├── ApplicationContextAwareProcessor.java
│ │ │ └── ClassPathXmlApplicationContext.java
│ │ ├── core
│ │ │ └── io
│ │ │ ├── ClassPathResource.java
│ │ │ ├── DefaultResourceLoader.java
│ │ │ ├── FileSystemResource.java
│ │ │ ├── Resource.java
│ │ │ ├── ResourceLoader.java
│ │ │ └── UrlResource.java
│ │ └── util
│ │ └── ClassUtils.java
│ └── resources
└── test
├── java
│ └── lqf
│ └── springframework
│ ├── SpringTest.java
│ └── service
│ ├── IUserService.java
│ ├── UserService.java
│ ├── UserServiceBeforeAdvice.java
│ └── UserServiceInterceptor.java
└── resources
├── important.properties
├── spring.xml
└── springPostProcessor.xml
AOP 动态代理融入到Bean的生命周期中类关系,如图:

- 整个类关系图中可以看到,在以 BeanPostProcessor 接口实现继承的 InstantiationAwareBeanPostProcessor 接口后,做了一个自动代理创建的类
DefaultAdvisorAutoProxyCreator,这个类的就是用于处理整个 AOP 代理融入到 Bean 生命周期中的核心类。 - DefaultAdvisorAutoProxyCreator 会依赖于拦截器、代理工厂和Pointcut与Advisor的包装服务
AspectJExpressionPointcutAdvisor,由它提供切面、拦截方法和表达式。 - Spring 的 AOP 把 Advice 细化了 BeforeAdvice、AfterAdvice、AfterReturningAdvice、ThrowsAdvice,目前我们做的测试案例中只用到了
BeforeAdvice,这部分可以对照 Spring 的源码进行补充测试。
设计
在有了AOP的核心功能实现后,把这部分功能服务融入到 Spring 其实也不难,只不过要解决几个问题,包括:怎么借着 BeanPostProcessor
把动态代理融入到 Bean 的生命周期中,以及如何组装各项切点、拦截、前置的功能和适配对应的代理器。整体设计结构如下图:

- 为了可以让对象创建过程中,能把xml中配置的代理对象也就是切面的一些类对象实例化,就需要用到 BeanPostProcessor
提供的方法,因为这个类的中的方法可以分别作用与 Bean 对象执行初始化前后修改 Bean 的对象的扩展信息。但这里需要集合于
BeanPostProcessor 实现新的接口和实现类,这样才能定向获取对应的类信息。 - 但因为创建的是代理对象不是之前流程里的普通对象,所以我们需要前置于其他对象的创建,所以在实际开发的过程中,需要在
AbstractAutowireCapableBeanFactory#createBean 优先完成 Bean 对象的判断,是否需要代理,有则直接返回代理对象。 - 这里还包括要解决方法拦截器的具体功能,提供一些 BeforeAdvice、AfterAdvice
的实现,让用户可以更简化的使用切面功能。除此之外还包括需要包装切面表达式以及拦截方法的整合,以及提供不同类型的代理方式的代理工厂,来包装切面服务。
实现
定义 Advice 拦截器链
源码1: lqf.springframework.aop.BeforeAdvice
源码2: lqf.springframework.aop.MethodBeforeAdvice
- 在 Spring 框架中,Advice 都是通过方法拦截器 MethodInterceptor 实现的。环绕 Advice 类似一个拦截器的链路,Before
Advice、After advice等,不过暂时我们需要那么多就只定义了一个 MethodBeforeAdvice 的接口定义。
定义 Advisor 访问者
源码1: lqf.springframework.aop.Advisor
源码2: lqf.springframework.aop.PointcutAdvisor
- PointcutAdvisor 承担了 Pointcut 和 Advice 的组合,Pointcut 用于获取 JoinPoint,而 Advice 决定于 JoinPoint 执行什么操作。
源码3: lqf.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor
- AspectJExpressionPointcutAdvisor 实现了 PointcutAdvisor 接口,把切面 pointcut、拦截方法 advice 和具体的拦截表达式包装在一起。这样就可以在
xml 的配置中定义一个 pointcutAdvisor 切面拦截器了。
方法拦截器
源码: lqf.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor
- MethodBeforeAdviceInterceptor 实现了 MethodInterceptor 接口,在 invoke 方法中调用 advice 中的 before 方法,传入对应的参数信息。
- 而这个 advice.before 则是用于自己实现 MethodBeforeAdvice 接口后做的相应处理。
代理工厂
源码: lqf.springframework.aop.framework.ProxyFactory
- 代理工厂主要解决的是关于 JDK 和 Cglib 两种代理的选择问题,有了代理工厂就可以按照不同的创建需求进行控制。
融入Bean生命周期的自动代理创建者
源码: lqf.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator
- DefaultAdvisorAutoProxyCreator 类的主要核心实现在于 postProcessBeforeInstantiation 方法中,从通过
beanFactory.getBeansOfType 获取 AspectJExpressionPointcutAdvisor 开始。 - 获取了 advisors 以后就可以遍历相应的 AspectJExpressionPointcutAdvisor 填充对应的属性信息,包括:目标对象、拦截方法、匹配器,之后返回代理对象即可。
- 现在调用方获取到的这个 Bean 对象就是一个已经被切面注入的对象了,当调用方法的时候,则会被按需拦截,处理用户需要的信息。
融入到Bean的生命周期
源码: lqf.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
- 因为创建的是代理对象不是之前流程里的普通对象,所以我们需要前置于其他对象的创建,即需要在
AbstractAutowireCapableBeanFactory#createBean 优先完成 Bean 对象的判断,是否需要代理,有则直接返回代理对象。
总结
- 本章节实现 AOP 功能的外在体现主要是把以前自己在单元测试中的切面拦截,交给 Spring 的 xml 配置了,也就不需要自己手动处理了。
- 一个功能的实现往往包括核心部分、组装部分、链接部分,为了这些各自职责的分工,则需要创建接口和类,由不同关系的继承、实现进行组装。
- 目前实现的 AOP 与 Spring 源码中的核心逻辑是类似的,但更会偏简单一些,也不会考虑更多的复杂场景遇到的问题,包括是否有构造函数、是否为代理中的切面等。
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 iAuzre
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果
音乐天地