前言
SpringAOP在Spring框架中占据了非常重要的位置,所提供的面向切面编程(AOP)是对面向对象编程(OOP)的一种补充。AOP采用横切的的方式,将核心业务与通用逻辑切分开来。可以更好的服用代码以及项目管理。
理论部分
Aspect:切面
aspect是由pointcut和advice组成的。它包含了横切逻辑定义和横切点定义。Spring AOP就是实现切面编程的框架,它将切面所定义的横切逻辑织入连接点中。Spring AOP的重心在如何将横切逻辑织入到目标连接点上,这里包含两个工作:
1. 如何通过pointcut和advice定位到joinpoint上
2. 如何在advice中编写切面代码
Advice:增强
由aspect添加到特定的joinpoint上的一段代码,在许多的AOP框架中,也包括Spring AOP,都会将advice模拟为一个拦截器(interceptor),并且在joinpoint上维护多个advice,进行层层拦截。
Joinpoint:连接点
方法的执行点。
Pointcut:切点
Advice和特定的pointcut相关联,并且在匹配的joinpoint中执行。
关于join point 和 point cut 的区别
joinpoint是描述那些方法可以被advice增强,joinpoint是具体的织入的地方。advice是在joinpoint上执行,而pointcut规定了那些joinpoint可以执行哪些advice。
入口
我们的自定义代码中,扫描到包含有@EnableAspectJAutoProxy注解的,就引入了AOP的依赖。其中的引入逻辑是在AspectJAutoProxyRegistrar中定义的。
@Aspect
@Component
@EnableAspectJAutoProxy
public class AspectDefinition {
@Pointcut("execution(* com.chudichen.spring.aop.*.getTestStr(..))")
public void pointcut() {
}
@Around("pointcut()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("Execute aop method");
return proceedingJoinPoint.proceed();
}
}
继续点击进入@EnableAspectJAutoProxy可以看到AspectJAutoProxyRegistrar。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
/**
* Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
* to standard Java interface-based proxies. The default is {@code false}.
*/
boolean proxyTargetClass() default false;
/**
* Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
* for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
* Off by default, i.e. no guarantees that {@code AopContext} access will work.
* @since 4.3.1
*/
boolean exposeProxy() default false;
}
具体的注册逻辑,调用了AopConfigUtils的registerAspectJAnnotationAutoProxyCreatorIfNecessary方法。
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
/**
* Register, escalate, and configure the AspectJ auto proxy creator based on the value
* of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
* {@code @Configuration} class.
*/
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
向registry中注册AnnotationAwareAspectJAutoProxyCreator.class
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
深入AnnotationAwareAspectJAutoProxyCreator
首先AnnotationAwareAspectJAutoProxyCreator的类结构图如下:
可以看到AnnotationAwareAspectJAutoProxyCreator实现了BeanPostProcessor,BeanPostProcessor中有两个方法postProcessBeforeInitialization和postProcessAfterInitialization,这里的AOP实现是在postProcessAfterInitialization中。
根据之前分析IOC源码的过程,可以知道Spring容器中的单例实例的创建是在AbstractApplicationContext中的refresh()里面的finishBeanFactoryInitialization()里面完成的。
因此AOP的增强逻辑的入口也是从finishBeanFactoryInitialization开始逐步的分析。
时序图:
第一步就是先找到增强逻辑advice,入口是从创建单例bean之后的initializeBean(),在此方法包含有执行后置处理器的逻辑,AOP的增强就是在后置处理器中实现的。
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
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()) {
// 执行后置处理器,AOP增强
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
接着进入到applyBeanPostProcessorsBeforeInitialization,这里的逻辑就是依次执行在容器中注册的后置处理器。AOP的后置处理器是AnnotationAwareAspectJAutoProxyCreator,后置处理器的实现是在AbstractAutoProxyCreator中。
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
执行AOP的后置处理器逻辑,具体构建逻辑是在wrapIfNecessary中。
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
上半段的逻辑是验证是否需要增强,不需要则直接跳过,如果需要增强,进一步来寻找增强逻辑(Advice)。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && 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;
}
// 寻找增强逻辑
// Create proxy if we have advice.
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;
}
通过getAdvicesAndAdvisorsForBean()方法来寻找增强逻辑,之前配置的pointcut也在这里使用。实现部分的代码是在AbstractAdvisorAutoProxyCreator里面。具体的查询逻辑还需要更进一步到findEligibleAdvisors当中,首先是查询出所有的Advisor,然后进行匹配,最后按照设置好的优先级进行排序。
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 查询出所有的Advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 匹配到合适的Advisor
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
// 按照优先级进行排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
findCandidateAdvisors()的逻辑是在子类AnnotationAwareAspectJAutoProxyCreator中实现的,通过BeanFactoryAspectJAdvisorsBuilder来构建Advisor列表。
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
continue;
}
// We must be careful not to instantiate beans eagerly as in this case they
// would be cached by the Spring container but would not have been weaved.
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
// 如果是Aspect的bean就添加到Advisor列表中
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
// Per target or per this.
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
List<Advisor> advisors = new ArrayList<>();
for (String aspectName : aspectNames) {
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
创建代理对象
解析完匹配的拦截器(Advisor)列表之后,就可以进行代理对象的创建了,进入到创建的核心逻辑createProxy()当中。首先就是按照Spring的惯例套路,在执行创建之前,先做大量的准备工作,比如说验证以及ProxyFactory的创建。
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
// 将beanName设置为目标代理类
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);
}
}
// 封装通知,然后将Advisors添加到ProxyFactory中
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
// 设置dialing类
proxyFactory.setTargetSource(targetSource);
// 定制代理
customizeProxyFactory(proxyFactory);
// 用来控制代理工厂被装配之后,是否允许修改通知,默认值为false,即在代理配置之后,不允许修改代理配置。
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
中间的过程包含了一步转换的操作buildAdvisors()。
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
// 解析拦截器名并注册
// Handle prototypes correctly...
Advisor[] commonInterceptors = resolveInterceptorNames();
List<Object> allInterceptors = new ArrayList<>();
if (specificInterceptors != null) {
// 将通知都封装在allInterceptors中
allInterceptors.addAll(Arrays.asList(specificInterceptors));
if (commonInterceptors.length > 0) {
if (this.applyCommonInterceptorsFirst) {
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
}
else {
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
if (logger.isTraceEnabled()) {
int nrOfCommonInterceptors = commonInterceptors.length;
int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
}
Advisor[] advisors = new Advisor[allInterceptors.size()];
for (int i = 0; i < allInterceptors.size(); i++) {
// 使用advisorAdapterRegistry这个适配器来包装通知
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
}
return advisors;
}
最后则是使用创建好的工厂来生成代理对象。到此AOP的源码解析完成了一大步了,由于篇幅较长,h2后续的CGlib和JDK生成代理的过程单独拆分出来。
总结
1. 首先可以借鉴的是Spring的代码结构,层层包裹,子类为父类提供具体的实现逻辑,父类来定义比较宏观的操作,也可以利用模板方法设计模式。
2. 将解析到的通知存储到缓存中。
3. 从缓存中获取通知,再筛选通知。
4. 包装通知,初始化ProxyFactory。
5. 使用ProxyFactory来创建代理(JDK动态代理、CGlib代理)。
6. 代理最终实现AOP的核心逻辑。