Spring AOP源码走读
简介
Spring的两大核心就是IOC和AOP,了解其机制可以有效的提高我们对于spring的理解和运用。在上一篇SpringIOC源码走读中我们已经大致了解了Spring IOC的原理。现在我们可以继续学习一下AOP了,因为AOP的实现其实也是依赖于IOC的。为了方便起见,这里我们使用注解式的方式。
spring aop面向切面编程的实际就是对bean进行代理,并把代理对象交给spring管理。
spring代理对象的方式有两种java动态代理和cglib代理。
准备工作
导入AOP相关依赖,这里不赘述
定义一个切面类和通知类
public class Calculate {
public int add(int a, int b) {
System.out.println("invoke Calculate.add()");
return a + b;
}
}
很简单,就是一个加法,打印一条语句便于查看方法运行。
@Aspect
public class CalculateAdvisor {
@Pointcut("execution(public int com.liyanan.springmvc.Calculate.add(..))")
public void pointCut() {}
@Before("pointCut()")
public void before(JoinPoint joinPoint) {
System.out.println(String.format("before method [%s], args[%d,%d]"
, joinPoint.getSignature(), joinPoint.getArgs()[0], joinPoint.getArgs()[1]));
}
@After("pointCut()")
public void after(JoinPoint joinPoint) {
System.out.println(String.format("after method [%s], args[%d,%d]"
, joinPoint.getSignature(), joinPoint.getArgs()[0], joinPoint.getArgs()[1]));
}
}
使用@Aspect告知Spring这是一个通知类,使用@Pointcut定义切入点。使用@Before等定义前置通知等等。
spring aop有五种通知形式:
1.@Before 前置通知
2.@After 后置通知
3.@AfterReturning 返回通知
4.@AfterThrowing 异常通知
5.@Around 环绕通知
这里我们就使用前置和后置两个简单的通知。
定义Configuration java配置类
@EnableAspectJAutoProxy
@Component
public class CalculateConfiguration {
@Bean
public Calculate calculate() {
return new Calculate();
}
@Bean
public CalculateAdvisor calculateAdvisor() {
return new CalculateAdvisor();
}
}
@Component表示这是一个java配置类,没有使用过的朋友可以把它当成一个spring xml配置文件中的根标签。里面的@Bean告知spring容器要注入这个bean,可以当成spring xml中的标签。
@EnableAspectJAutoProxy表示spring开启代理。
编写单元测试
public class CalculateTest {
@Test
public void testAdd() {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(CalculateConfiguration.class);
Calculate calculate = context.getBean(Calculate.class);
calculate.add(1, 2);
}
}
运行结果
before method [int com.liyanan.springmvc.Calculate.add(int,int)], args[1,2]
invoke Calculate.add()
after method [int com.liyanan.springmvc.Calculate.add(int,int)], args[1,2]
可以看到,虽然我们从context中获取的是calculate对象,但是运行后的结果是我们的通知成功的被织入了。
开始阅读源码
SpringAOP的核心@EnableAspectJAutoProxy
点进去EnableAspectJAutoProxy我们可以发现@Import(AspectJAutoProxyRegistrar.class),说明EnableAspectJAutoProxy注解导入了AspectJAutoProxyRegistrar这个类对象。
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
他通过AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary()向容器中注入一个name为internalAutoProxyCreator的AnnotationAwareAspectJAutoProxyCreator类对象。
也就是AOP的核心处理逻辑在AnnotationAwareAspectJAutoProxyCreator中。
梳理AnnotationAwareAspectJAutoProxyCreator的继承关系如下:
- ==> {@link org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator}
-
==> {@link org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator}
-
==> {@link org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator}
-
==> {@link org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator}
-
==> {@link org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor}
-
==> {@link org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor}
-
==> {@link org.springframework.beans.factory.config.BeanPostProcessor}
可以看出AnnotationAwareAspectJAutoProxyCreator其实就是一个bean后置处理器, 根据我们在上一篇Spring IOC的源码可以知道,beanPostProcessor是在bean初始化前后对bean进行一些我们想要的操作。所以我们可以追踪后置处理器的前处理方法和后处理方法。
我们找到AbstractAutoProxyCreator重写了postProcessAfterInitialization后置处理方法。可以在这里打上断点追踪。
跟踪上面的断点,可以看到在spring ioc注入Calculate对象的时候,
AbstractAutowireCapableBeanFactory#initializeBean(String, Object, org.springframework.beans.factory.support.RootBeanDefinition)
执行AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization(Object, String)后置bean后置处理器方法。
代理逻辑:
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator
postProcessAfterInitialization
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
wrapIfNecessary
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
createProxy
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) { AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
buildAdvisors 找到所有用于该对象的通知
proxyFactory.getProxy(getProxyClassLoader()) 获取代理对象
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
createAopProxy()确定使用cglib还是jdk动态代理生成代理对象
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
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.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
从这里可以看出spring判断Calculate是否实现接口,如果实现优先使用java动态代理生成代理对象,否则使用cglib代理对象。
总结
Spring AOP的核心就是AnnotationAwareAspectJAutoProxyCreator这个后置处理器在创建bean对象的时候在后置处理方法中对该bean对象进行代理,最后吧代理对象返回交给Spring容器。