Spring AOP源码分析

文章目录

    • 概要
    • 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
上一篇:基于词级ngram的词袋模型对twitter数据进行情感分析


下一篇:VisualRules-Web案例展示(一)