Spring源码学习——AOP实现方式及原理

SpringAOP源码解析

  • 以下为个人有道笔记的内容迁移

1.核心实现原理 :动态代理

  • jdk动态代理
  • cglib动态代理

2.核心实现接口:BeanPostProcessor

该类bean被注册到beanfactory之后,会针对每一个生成的bean进行处理,可以加上前置后置方法调用

3.基础实现demo

注意切面类也需要component注解

@Aspect
@Component
public class MyAspect {
 
	@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("before1");
		Object o = null;
		try {
			o = p.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		System.out.println("after1");
		return o;
	}
}

4.源码解读

xml配置项:
<aop:aspectj-autoproxy proxy-target-class="true" />

根据之前查看到的解析xml过程,可以知道解析aop的handler在aop包中的spring.handlers中定义,解析类为AopNamespaceHandler;(不太清楚的可以看Spring源码学习——解析xml文章中最后解析非默认节点的部分)

查看init方法可以知道,该元素的parser类为AspectJAutoProxyBeanDefinitionParser

4.1 初始化

在parser的parse方法内注册一个internalAutoProxyCreator到beanfactory,具体类为
AnnotationAwareAspectJAutoProxyCreator

/*
初始化核心方法:
BeanFactory中注册一个AnnotationAwareAspectJAutoProxyCreator,
beanname为org.springframework.aop.config.internalAutoProxyCreator
同时解析proxy-targetclass等属性
*/
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);

4.2 BeanPostProcessor包装bean

针对AOP来说,主要集中在bean初始化完成后的后置包装

回到refresh方法(AbtractApplicationContext),调用堆栈如下:
该部分的跳转流程待补充

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean()
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean()
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean()
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject()
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton()
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean()
org.springframework.beans.factory.support.AbstractBeanFactory.getBean()
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons()
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization()
org.springframework.context.support.AbstractApplicationContext.refresh()
org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh()
org.springframework.boot.SpringApplication.refresh()

查看AbstractAutowireCapableBeanFactory的initializeBean方法,可以看到在bean初始化前后都使用了已有的BeanPostProcessor完成了前置包装和后置包装。

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
	//此处返回的是被前置包装的bean
	wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

try {
	//此处完成bean的初始化,包括afterPropertiesSet方法的调用
	invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
	throw new BeanCreationException(
			(mbd != null ? mbd.getResourceDescription() : null),
			beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
	//此处返回的是被后置包装的bean
	wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

以初始化完成后的包装为例:注意在前置包装中不会完成aop包装

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
		throws BeansException {

	Object result = existingBean;
	//此处针对所有的BeanPostProcessor进行了后置方法(postProcessAfterInitialization)的包
	//也包括proxycreator
	for (BeanPostProcessor processor : getBeanPostProcessors()) {
		Object current = processor.postProcessAfterInitialization(result, beanName);
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}

4.3 如何进行包装

核心方法(针对internalAutoProxyCreator的bean)

  • postProcessAfterInitialization在bean初始化完成后进行包装

该方法的实现在AbstractAutoProxyCreator类中,在该类中可以发现前置包装方法直接返回bean。

后置包装主要调用wrapIfNecessary方法,在其中会判断是否可切,并且创建代理

//Create proxy if we have advice.
//该方法用于判断bean中是否存在切点,实现见AbstractAdvisorAutoProxyCreator类
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
	//缓存,用于存放该bean是否被环绕
	this.advisedBeans.put(cacheKey, Boolean.TRUE);
	//创建代理,核心方法
	Object proxy = createProxy(
			bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
	this.proxyTypes.put(cacheKey, proxy.getClass());
	//返回代理替代原有bean
	return proxy;
}

this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;

继续跟进createProxy方法,发现创建proxyfactory并将适用切点传入

随后通过ProxyFactory的getProxy获取代理

public Object getProxy(@Nullable ClassLoader classLoader) {
      return createAopProxy().getProxy(classLoader);
}

4.3.1 决定适用jdk代理还是cglib代理--createAopProxy方法

//1:是否优化
//2:是否目标已被代理
//3:是否存在代理接口
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
	Class<?> targetClass = config.getTargetClass();
	if (targetClass == null) {
		throw new AopConfigException("TargetSource cannot determine target class: " +
				"Either an interface or a target is required for proxy creation.");
	}
	//目标类为接口或代理类,适用jdk代理
	if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
		return new JdkDynamicAopProxy(config);
	}
	//其他情况适用cglib
	return new ObjenesisCglibAopProxy(config);
}
else {
	return new JdkDynamicAopProxy(config);
}

4.3.2 适用proxy获取代理-jdk为例

返回的JdkDynamicAopProxy继承了InvocationHandler,实质上生成代理对象时

public Object getProxy(@Nullable ClassLoader classLoader) {
	if (logger.isTraceEnabled()) {
		logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
	}
	//
	Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
	findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
	//传入本身作为invocationhandler
	return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

在调用bean方法时,实质上是执行代理中的invoke方法,在invoke方法中会获取当前调用方法适用的切面,并且使用ReflectiveMethodInvocation完成切面方法链的调用。。

posted @ 2020-06-04 21:35  快乐肥宅  阅读(267)  评论(0编辑  收藏  举报