文章目录
Spring的AOP源码详解
本文主要介绍Spring AOP原理解析的切面实现过程(将切面类的所有切面方法根据使用的注解生成对应的增强Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor,为后续交给代理增强实现做准备的过程)
简单使用
@Configuration
@EnableAspectJAutoProxy
public class SpringConfig {
}
@Aspect
@Component
@Slf4j
public class LogAspect {
@Pointcut("@annotation(com.lijunhua.advice.log.Logger)")
public void pc() {
}
@Around("pc()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
//1、调用开始...
String param = JSON.toJSONString(joinPoint.getArgs());
//开始时间
long start = System.currentTimeMillis();
Object result = null;//返回结果 当异常时修改返回结果
//执行
try {
result = joinPoint.proceed();
} catch (Exception e) {
log.error("soa method error,param = {}", param);
throw e;
}
//结束时间
long end = System.currentTimeMillis();
log.info("soa method end,start time:{}; end time:{}; Run Time:{}(ms), param={}, result = {}", start, end, (end - start), param, JSON.toJSONString(result, SerializerFeature.DisableCircularReferenceDetect));
return result;
}
}
本文只分析AOP的注解实现原理
@EnableAspectJAutoProxy解析
@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;
}
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
private final Log logger = LogFactory.getLog(getClass());
/**
* 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) {
// 就是在往传入的BeanDefinitionRegistry registry中注册BeanDefinition。
// 注册了BeanDefinition之后,Spring就会去实例化这个Bean,从而达到AspectJAutoProxy作用
// 添加到Spring上下文中的AnnotationAwareAspectjAutoProxyCreator对象
// AnnotationAwareAspectjAutoProxyCreator对象其实就是这个类型InstantiationAwareBeanPostProcessor
// 在createbean时调用resolveBeforeInstantiation(beanName, mbdToUse),
// 会首先调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法,可以在此处返回代理的对象
if(logger.isInfoEnabled()){
logger.info("加入AOP处理的类的bd到bdMap中,该类名为:AnnotationAwareAspectJAutoProxyCreator");
}
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);
}
}
}
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
// 如果注册表中已经存在beanName=org.springframework.aop.config.internalAutoProxyCreator的bean,
// 则按优先级进行选择。
// beanName=org.springframework.aop.config.internalAutoProxyCreator,可能存在的beanClass有三种,
// 按优先级排序如下:
// InfrastructureAdvisorAutoProxyCreator、
// AspectJAwareAdvisorAutoProxyCreator、
// AnnotationAwareAspectJAutoProxyCreator
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
// 拿到已经存在的bean定义
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
// 如果已经存在的bean的className与当前要注册的bean的className不相同,则按优先级进行选择
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
// 拿到已经存在的bean的优先级
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
// 拿到当前要注册的bean的优先级
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
// 如果当前要注册的bean的优先级大于已经存在的bean的优先级,则将bean的className替换为当前要注册的bean的className,
apcDefinition.setBeanClassName(cls.getName());
}
// 如果小于,则不做处理
}
// 如果已经存在的bean的className与当前要注册的bean的className相同,则无需进行任何处理
return null;
}
// 如果注册表中还不存在,则新建一个Bean定义,并添加到注册表中
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
// 设置了order为最高优先级
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 注册BeanDefinition,beanName为org.springframework.aop.config.internalAutoProxyCreator
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
小结
- 利用@Import导入AspectJAutoProxyRegistrar类,该类实现ImportBeanDefinitionRegistrar接口
- 在解析AspectJAutoProxyRegistrar的registerBeanDefinitions方法是注册BeanDefinition,这里面注册了AnnotationAwareAspectJAutoProxyCreator的BeanDefinition,后续实例化以及初始化该类,在处理AOP的增强逻辑。
@Aspect的解析
即形成Advisor的过程
解析的时机
初次从spring容器中获取第一个bean时,调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法时,调用createBean方法—>resolveBeforeInstantiation方法—>调用容器中所有的InstantiationAwareBeanPostProcessor的实现类的postProcessBeforeInstantiation方法
真正解析步骤
最终调到AbstractAutoProxyCreator的postProcessBeforeInstantiation方法
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
// bean的类是aop基础设施类 || 使用@Aspect注解
// 在shouldSkip中初始化了所有的AOP的advisor以及事务的advisor
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
分析shouldSkip方法
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// Consider optimization by caching the list of the aspect names
// 找到容器中所有的Advisor,含AOP和Spring事务
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
// 名称相同
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
return super.shouldSkip(beanClass, beanName);
}
最终调到AnnotationAwareAspectJAutoProxyCreator的findCandidateAdvisors方法
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
// 添加根据父类规则找到的所有advisor。
List<Advisor> advisors = super.findCandidateAdvisors(