前言
我之前在看源码都是局限于其中一步、两步没有一个整体观,我们在看源码的时候如果能在一个整体观去看,很多时候有些内容就豁然开朗了。
介绍
我们先看一下,整改spring容器启动这个流程,其中AOP 就在 初始化Bean后面由BeanPostProccessor 进行后置处理将Bean替换为AOP的代理类进行操作。
如果我们认识到这一点那么我们就有两个需要重点关注:
第一个是关于BeanPostProccessor 实现类对容器的注入。
第二个是BeanPostProccessor 的实现类对Bean本身代理处理。
实践
1、贴出一个切面
@Aspect
public class AspectJTest {
@Pointcut("execution(* *.say(..))")
public void test(){}
@Before("test()")
public void before(){
System.out.println("before test..");
}
@After("test()")
public void after(){
System.out.println("after test..");
}
@Around("test()")
public Object around(ProceedingJoinPoint p){
System.out.println("around before");
Object o = null;
try {
o = p.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("around after");
return o;
}
}
2、切入点
public interface Person {
void say();
}
class Student implements Person {
@Override
public void say() {
System.out.println("这是一个苦逼的程序员");
}
}
3、bean.xml的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<aop:aspectj-autoproxy/>
<bean id="student" class="com.megvii.winterolympicvillage.provider.aop.Student"/>
<bean class="com.megvii.winterolympicvillage.provider.aop.AspectJTest"/>
</beans>
4、测试类
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
Person bean2 = (Person) ac.getBean("student");
bean2.say();
}
}
源码解析
我们在调用 ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext(“beans.xml”); 之后会进入我们最常见
AbstractApplicationContext#refresh源码 部分。主要在这个地方对各个部分进行串联。
由前面流程图可知,将解析xml文件获取beanFactory 内容,这一步获取xml中内容,也是这一步注册BeanPostProccessor 到工厂中,对Bean 进行包装。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//刷新前的预处理;
prepareRefresh();
//获取BeanFactory;默认实现是DefaultListableBeanFactory,在创建容器的时候创建的(这一步解析BeanDefinitions)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//BeanFactory的预准备工作(BeanFactory进行一些设置,比如context的类加载器,BeanPostProcessor和XXXAware自动装配等)
prepareBeanFactory(beanFactory);
try {
//BeanFactory准备工作完成后进行的后置处理工作
postProcessBeanFactory(beanFactory);
//执行BeanFactoryPostProcessor的方法;
invokeBeanFactoryPostProcessors(beanFactory);
//注册BeanPostProcessor(Bean的后置处理器),在创建bean的前后等执行
registerBeanPostProcessors(beanFactory);
//初始化MessageSource组件(做国际化功能;消息绑定,消息解析);
initMessageSource();
//初始化事件派发器
initApplicationEventMulticaster();
//子类重写这个方法,在容器刷新的时候可以自定义逻辑;如创建Tomcat,Jetty等WEB服务器
onRefresh();
//注册应用的监听器。就是注册实现了ApplicationListener接口的监听器bean,这些监听器是注册到ApplicationEventMulticaster中的
registerListeners();
//初始化所有剩下的非懒加载的单例bean
finishBeanFactoryInitialization(beanFactory);
//完成context的刷新。主要是调用LifecycleProcessor的onRefresh()方法,并且发布事件(ContextRefreshedEvent)
finishRefresh();
}
......
}
源码解析
获取BeanFactory;默认实现是DefaultListableBeanFactory,在创建容器的时候创建的(这一步解析BeanDefinitions)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 会对xml文件进行解析
对<aop:aspectj-autoproxy/> 的解析过程中,针对获取元素进行注册。
可以看到在解析过程中将对aop:aspectj-autoproxy/ 会将AnnotationAwareAspectJAutoProxyCreator.class 进行注册
我们看一下AnnotationAwareAspectJAutoProxyCreator.class 的集成关系
可以看到AnnotationAwareAspectJAutoProxyCreator 是继承BeanPostProccessor
那么在Bean 初始化后会对由BeanPostProccessor 进行后置处理将Bean替换为AOP的代理类进行操作。对后面两个bean 的初始化不在这个关心的重点就跳过。
源码解析
可以看到在初始之后确实进行aop的后置操作,最终创建DefaultAopProxyFactory进行JDK 代理
返回装饰对象AOP对象
当aop调用数据的时候,使用创建一个调用链,进行调用