文章目录
- 概要
- Bean后置处理器
- 代理对象调用使用责任链模式
概要
以下是用于debug Spring AOP源码得测试代码:
@Aspect//声明这是一个切面
@Component//声明这是一个组件
/**
* 执行顺序
* @Around进入环绕通知...
* @Before进入前置通知:[]
* 进入实现类 work.....
* @Around方法执行耗时>>>>>: 1001
* @After进入后置通知...
* @AfterReturning进入最终通知...End!
*/
public class SlaverAspect {
//环绕通知(连接到切入点开始执行,下一步进入前置通知,在下一步才是执行操作方法)
@Around(value = "pointCut()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("@Around进入环绕通知...");
long startTime = System.currentTimeMillis();
// 调用了下一个拦截器,递归调用ReflectiveMethodInvocation#proceed
joinPoint.proceed();
long endTime = System.currentTimeMillis();
System.out.println(String.format("@Around方法执行耗时>>>>>: %s", endTime - startTime));
}
//前置通知(进入环绕后执行,下一步执行方法)
@Before(value = "pointCut()")
public void before(JoinPoint joinPoint) {
System.out.println("@Before进入前置通知:" + Arrays.toString(joinPoint.getArgs()));
}
//异常通知(出错时执行)
@AfterThrowing(value = "pointCut()", throwing = "ex")
public void afterThrowing(JoinPoint joinPoint, Throwable ex) {
System.out.println("@AfterThrowing进入异常通知" + Arrays.toString(joinPoint.getArgs()));
}
//后置通知(返回之前执行)
@After(value = "pointCut()")
public void after() {
System.out.println("@After进入后置通知...");
}
//最终通知(正常返回通知,最后执行,出现异常)
@AfterReturning(value = "pointCut()")
public void afterReturning() {
System.out.println("@AfterReturning进入最终通知...End!");
}
//定义一个切入点 后面的通知直接引入切入点方法pointCut即可
//参数:
//第一个”*“符号;表示返回值的类型任意
//.*(..)表示任何方法名,括号表示参数,两个点表示任何参数类型
@Pointcut(value = "execution(* com.spring.test.aop.impl.SlaverImpl.*(..))")
public void pointCut() {
System.out.println("@进入切点...");
}
}
测试类
public interface Slaver {
void work();
}
@Service
public class SlaverImpl implements Slaver {
//用来织入AOP的通知方法
@Override
public void work() {
System.out.println("进入实现类work.....");
try {
Thread.sleep(1000);
//此处决定拦截器的走向
// int s=1/0;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
测试入口
public class Main {
public static void main(String[] args) throws InterruptedException {
ApplicationContext context =
new ClassPathXmlApplicationContext("classpath*:application-aop.xml");
Slaver slaver = (Slaver) context.getBean("slaverImpl");
//使用代理调用了JdkDynamicAopProxy.invoke
slaver.work();
System.out.printf(slaver.getClass().getName());
// Thread.sleep(Integer.MAX_VALUE);
System.out.println("over>>>>>>>>>>");
Cglib动态代理(不实现接口)
// SlaverImpl slaver = (SlaverImpl) context.getBean("slaverImpl");
// //使用代理调用了JdkDynamicAopProxy.invoke
// slaver.work();
// System.out.println(">>>>>>>>>>"+slaver);
// AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Object.class);
// ApplicationContext context2 =
// new FileSystemXmlApplicationContext("classpath*:application-aop.xml");
}
}
Bean后置处理器
在IOC容器主流程中:
@Override
public void refresh() throws BeansException, IllegalStateException {
// synchronized块锁(monitorenter --monitorexit)
// 不然 refresh() 还没结束,又来个启动或销毁容器的操作
// startupShutdownMonitor就是个空对象,锁
synchronized (this.startupShutdownMonitor) {
//1、【准备刷新】,设置了几个变量,也是准备工作
prepareRefresh(); // ===>
// 2、【获得新的bean工厂】关键步骤,重点!
//2.1、关闭旧的 BeanFactory
//2.2、创建新的 BeanFactory(DefaluListbaleBeanFactory)
//2.3、解析xml/加载 Bean 定义、注册 Bean定义到beanFactory(不初始化)
//2.4、返回全新的工厂
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // ===>
//3、【bean工厂前置操作 】为BeanFactory配置容器特性
// 例如类加载器、表达式解析器、注册默认环境bean、后置管理器
prepareBeanFactory(beanFactory); // ===>
try {
// 4、【bean工厂后置操作】此处为空方法,如果子类需要,自己去实现
postProcessBeanFactory(beanFactory); // ===> 空的!
//5、【调用bean工厂后置处理器】,开始调用我们自己实现的接口
//目标:
//调用顺序一:先bean定义注册后置处理器
//调用顺序二:后bean工厂后置处理器
invokeBeanFactoryPostProcessors(beanFactory); // ===>
//6、【注册bean后置处理器】只是注册,但是还不会调用
//逻辑:找出所有实现BeanPostProcessor接口的类,分类、排序、注册
registerBeanPostProcessors(beanFactory); // ===> 关键点
// Initialize message source for this context.
//7、【初始化消息源】国际化问题i18n,参照https://nacos.io/
initMessageSource(); // ===> 就是往factory加了个single bean
// Initialize event multicaster for this context.
//8、【初始化事件广播器】初始化自定义的事件监听多路广播器
// 如果需要发布事件,就调它的multicastEvent方法
// 把事件广播给listeners,其实就是起一个线程来处理,把Event扔给listener处理
// (可以通过 SimpleApplicationEventMulticaster的代码来验证)
initApplicationEventMulticaster(); // ===> 同样,加了个bean
// 9、【刷新】这是个protected空方法,交给具体的子类来实现
// 可以在这里初始化一些特殊的 Bean
// (在初始化 singleton beans 之前)
onRefresh(); // ===> 空的
//10、【注册监听器】,监听器需要实现 ApplicationListener 接口
// 也就是扫描这些实现了接口的类,给他放进广播器的列表中
// 其实就是个观察者模式,广播器接到事件的调用时,去循环listeners列表,
// 挨个调它们的onApplicationEvent方法,把event扔给它们。
registerListeners(); // ===> 观察者模式
//11、 【结束bean工厂初始化操作】
//1、初始化所有的 singleton beans,反射生成对象/填充
//2、 调用Bean的前置处理器和后置处理器
// 关键点:getBean方法里完成
finishBeanFactoryInitialization(beanFactory); // ===> 关键点
// 12、结束refresh操作
// 发布事件与清除上下文环境
finishRefresh();
} catch (BeansException ex) {
。。。
} finally {
。。。
}
}
}
在上面调用得方法finishBeanFactoryInitialization
触发了bean的后置处理器的调用
其中在后置处理器org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization
方法中
//如果当前的bean适合被代理,则需要包装指定的bean
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if (bean != null) {
// 根据给定的bean的class和name构建一个key
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
// 如果当前的bean适合被代理,则需要包装指定的bean
// aop:注意看这个bean,这还是SlaverImpl本尊,那么进去以后,情况变了~
return wrapIfNecessary(bean, beanName, cacheKey); // ===> aop 进!
}
}
return bean;
}
//1、判断当前bean是否已经生成过代理对象
//2、拿到切面类中的所有增强方法(拦截器:环绕、前置、后置等)
//3、生成代理对象
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 判断是否为空 否在TargetSource缓存中存在
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// advisedBeans缓存了不需要代理的bean(为false的),如果缓存中存在,则可以直接返回
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
//Infrastructure基础设施
// 判断bean是否为Spring自带bean,如果是,不用进行代理的
// shouldSkip()则用于判断当前bean是否应该被略过
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
// 对当前bean进行缓存
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
//AOP: 【关键点 1 】
// 找到哪些aspect的execution能匹配上当前bean
// 匹配上的话列出前后和置换的方法(拦截器:环绕、前置、后置等),并且!!排好顺序
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); // ===> debug进
//debug后,仔细看一下上面这个数组内的值,其实就是SlaverAspect里的匹配上的方法信息!
//如果有匹配上的方法,就生成代理对象【关键点!】
if (specificInterceptors != DO_NOT_PROXY) {
// 允许创建代理对象的,设置为true
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 【关键节点 2 】
// 开始创建AOP代理
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); // ===>
// 缓存生成的代理bean的类型,并且返回生成的代理bean
this.proxyTypes.put(cacheKey, proxy.getClass());
//此处返回的代理和在Main函数中返回的是一样的
//说明此处代理成功创建
return proxy;
}
//如果拿到的增强方法为空,缓存起来(使用false标记不需要代理)
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
//为true,DefaultListableBeanFactory
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
//标记一下,当前的bean具备创建代理的资格
// 其实就是在BD设置了属性setAttribute("originalTargetClass",bean的class),===>
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass); // ===>
}
//创建一个默认的代理工厂DefaultAopProxyFactory,注意:父类无参构造器
ProxyFactory proxyFactory = new ProxyFactory();
//proxyFactory通过复制配置进行初始化
//this为AbstractAutoProxyCreator对象,说明AbstractAutoProxyCreator继承参数实际类型
proxyFactory.copyFrom(this); // ===> 其实就是设置了一堆值
/**
* true
*目标对象没有接口(只有实现类) – 使用CGLIB代理机制
* false
* 目标对象实现了接口 – 使用JDK代理机制(代理所有实现了的接口)
*/
//默认值为false,为true,使用CGLIB,
if (!proxyFactory.isProxyTargetClass()) {
//来判断@EnableAspectJAutoProxy注解或者XML的proxyTargetClass参数(true或者false)
//也就是:用户有没有明确指定什么方式生成代理
// 我们没指定,此处false
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
} else {
//评估接口的合理性,一些内部回调接口,比如InitializingBean等不要,我们自己的加入proxyFactory
evaluateProxyInterfaces(beanClass, proxyFactory); // ===>
}
}
// 把把前面我们过滤出来的那些切面方法,转成Advisor数组
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
//加入到代理工厂
proxyFactory.addAdvisors(advisors);
//设置要代理的类(目标类)
proxyFactory.setTargetSource(targetSource);
//子类实现, 定制代理
customizeProxyFactory(proxyFactory);
//是否还允许修改通知,缺省值为false
proxyFactory.setFrozen(this.freezeProxy);
//设置预过滤
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//【关键点!】proxyFactory携带了aop里配置的各种切面方法等等,由它来创建代理
return proxyFactory.getProxy(getProxyClassLoader()); // 代理类诞生的地方,这里真正生产jdk还是cglib的动态代理
}
上面就是在bean的后置处理器中完成动态代理的创建过程,其中的类关系图如下:
代理对象调用使用责任链模式
public static void main(String[] args) throws InterruptedException {
ApplicationContext context =
new ClassPathXmlApplicationContext("classpath*:application-aop.xml");
Slaver slaver = (Slaver) context.getBean("slaverImpl");
//使用代理调用了JdkDynamicAopProxy.invoke
slaver.work();
System.out.printf(slaver.getClass().getName());
// Thread.sleep(Integer.MAX_VALUE);
System.out.println("over>>>>>>>>>>");
}
测试代码执行到work
方法时,会直接进入到org.springframework.aop.framework.JdkDynamicAopProxy#invoke
//1、调用增强方法
//2、反射调用目标方法
//重点关注:getInterceptorsAndDynamicInterceptionAdvice责任链方法
// 和invocation.proceed()方法(开始调用)
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
//一堆判断和加载,拖到最下面,看责任链部分,核心在那里。
Object oldProxy = null;
boolean setProxyContext = false;
//获取目标资源,此处就是slaverImpl,debug变量值试试
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
//当前方法是否等于Equals,如果是,则重写
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
return equals(args[0]);
//当前方法是否等于HashCode,如果是,则重写
} else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
return hashCode();
//方法声明类是否等于DecoratingProxy
} else if (method.getDeclaringClass() == DecoratingProxy.class) {
//使用反射直接进行调用目标资源
return AopProxyUtils.ultimateTargetClass(this.advised);
//方法声明是否接口 、或者是否Advised类型
} else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// 用代理配置对ProxyConfig进行服务调用。。。
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
//如果暴露;就放到ThreadLocal,默认不暴
if (this.advised.exposeProxy) {
// 放到ThreadLocal
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
//目标资源;对应业务实现类,这是我们的真身(SlaverImpl)
target = targetSource.getTarget();
//目标类;对应业务实现类
Class<?> targetClass = (target != null ? target.getClass() : null);
//【关键点 1 】构建责任链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // ===> a
// 如果为空,则直接调用target的method
if (chain.isEmpty()) {
//如果没有拦截器,直接调用
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); // 直接执行
} else {
//proxy代理对象
//target是目标类
//targetClass是目标类的class
//method是目标方法
//args是对应的方法参数
//chain是对应的拦截器
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
//!!!责任链即将开始调用的入口~~~
retVal = invocation.proceed(); // ===> 【关键点 2 】
}
//以下方法,在责任链执行完成后,才会跑到,就一些收尾工作
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy