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完成切面方法链的调用。。