Spring AOP工作原理概要
Spring AOP的工作原理主要分为以下几个主要流程:
1.解析读取配置,将AOP相关配置加载到bean定义中,注册AdvisorAutoProxyCreator增强器自动代理创建器
2.初始化bean过程中,在Bean后置处理器AbstractAutoProxyCreator初始化后置处理方法postProcessAfterInitialization,进行获取对应增强器并创建代理对象。
注册AdvisorAutoProxyCreator增强器自动代理创建器
Spring容器启动时,读取配置装载bean定义,会调用BeanDefinitionParser的parse方法,注册AdvisorAutoProxyCreator增强器自动代理创建器,配置方式分为注解配置与xml配置,本篇博客采用的是以xml配置方式。
当配置了
public BeanDefinition parse(Element element, ParserContext parserContext) {
CompositeComponentDefinition compositeDef =
new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
//注册自动代理创建器
configureAutoProxyCreator(parserContext, element);
List childElts = DomUtils.getChildElements(element);
for (Element elt: childElts) {
String localName = parserContext.getDelegate().getLocalName(elt);
if (POINTCUT.equals(localName)) {
//解析Pointcut配置
parsePointcut(elt, parserContext);
}
else if (ADVISOR.equals(localName)) {
//解析Advisor配置
parseAdvisor(elt, parserContext);
}
else if (ASPECT.equals(localName)) {
//解析Aspect配置
parseAspect(elt, parserContext);
}
}
parserContext.popAndRegisterContainingComponent();
return null;
}
public static void registerAspectJAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
//注册AspectJAutoProxyCreator
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
//对配置上设置proxy-target-class为true expose-proxy为true做处理
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
//注册组件
registerComponentIfNecessary(beanDefinition, parserContext);
}
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) {
//比较自动代理创建器的优先级,将className设置为优先级高的自动代理创建器的className
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);
//注册bean定义
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
创建AOP代理对象
Spring容器在实例化bean的过程中,会调用AbstractAutoProxyCreator的后置初始化处理方法postProcessAfterInitialization进行代理对象的创建,此过程中,将需要增强的代理对象会一一添加到advisedBeans中置为true作缓存处理。
主要流程大概分为增强器的获取与代理对象的创建。
public Object postProcessAfterInitialization(@Nullable 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;
}
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;
}
//Advice Pointcut Advisor类 不需要创建代理对象
//配置了指定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;
}
getAdvicesAndAdvisorsForBean方法获取增强器
获取增强器主要流程:
1.获取所有bean名称
2.遍历所有bean名称找出其中标记Aspect的bean
3.解析并构造获取bean的所有增强器
4.将解析到的增强器添加到缓存中
5.过滤匹配出当前bean的增强器
protected List findEligibleAdvisors(Class> beanClass, String beanName) {
// 查找所有的增强器
List candidateAdvisors = findCandidateAdvisors();
// 过滤匹配当前bean的增强器
List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
public List buildAspectJAdvisors() {
List aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List advisors = new LinkedList<>();
aspectNames = new LinkedList<>();
//获取所有beanName
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
//遍历所有beanName
for (String beanName : beanNames) {
// 不合法的bean则略过,由子类定义规则
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;
}
//找出注解@AspectJ的bean
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);
//解析标记AspectJ中的增强方法
List 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 advisors = new LinkedList<>();
//将解析到的增强器记录到缓存中
for (String aspectName : aspectNames) {
List 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;
}
public List getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
//获取标记为AspectJ的Class类型
Class> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
//获取标记为AspectJ的名称
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
//校验
validate(aspectClass);
// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
// so that it will only instantiate once.
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List advisors = new LinkedList<>();
//获取所有增强器方法,此处排除PointCut注解的增强器方法
for (Method method : getAdvisorMethods(aspectClass)) {
//对@Before、 @Around、@After、@AfterReturning、 @AfterThrowing注解的方法进行切面表达式设置并构造Advisor
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
// If it's a per target aspect, emit the dummy instantiating aspect.
//如果增强器方法不为空 && 配置了增强延迟初始化
//则在首位加入同步实例化增强器
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
// 获取DeclareParents注解的增强器
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
Class> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
AspectJAnnotation> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// If we get here, we know we have an AspectJ method.
// Check that it's an AspectJ-annotated class
if (!isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: " +
"Offending method '" + candidateAdviceMethod + "' in class [" +
candidateAspectClass.getName() + "]");
}
if (logger.isDebugEnabled()) {
logger.debug("Found AspectJ method: " + candidateAdviceMethod);
}
AbstractAspectJAdvice springAdvice;
//对@Before、 @Around、@After、@AfterReturning、 @AfterThrowing注解的方法进行切面表达式设置并构造具体的增强器Advisor
switch (aspectJAnnotation.getAnnotationType()) {
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfter:
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
// Now to configure the advice...
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();
return springAdvice;
}
createProxy方法创建代理对象
根据获取前面获取到的增强器,针对对应bean创建代理对象。
主要流程:
1.获取当前类中的属性
2.添加代理接口
3.封装Advisor并加入到ProxyFactory
4.为子类定制代理
5.进行代理操作,代理对象的创建实现方式有两种,一种是JDK原生的动态代理,用于创建接口的代理对象;一种是Cglib动态代理,可以创建接口和类的代理对象。当配置上的proxy-target-class设置为true,强制使用cglib做接口和类代理,缺点是无法advise通知final方法(无法覆写)
protected Object createProxy(Class> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
//代理工厂获取当前类属性
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
//判断bean是否应该使用targetClass而不是接口代理
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);
//用来控制代理工厂被配置之后,是否还允许修改通知
//默认值为false,代理被配置之后,不允许修改代理
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
// 解析所有注册的拦截器名称
Advisor[] commonInterceptors = resolveInterceptorNames();
List
动态代理
Spring对JDK动态代理封装了JdkDynamicAopProxy类,采用JDK原生的动态代理,即实现InvocationHandler接口,重写invoke方法实现方法的增强。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
//对equals和hashcode方法做处理
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
//Advised.class为 调用方法的class的自身类或子类 则直接调用切点方法
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
//暴露代理
if (this.advised.exposeProxy) {
// 目标对象自我调用无法实施切面增强则需要暴露代理
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
target = targetSource.getTarget();
Class> targetClass = (target != null ? target.getClass() : null);
// 获取当前方法的拦截器链
List
Spring对Cglib动态代理封装了CglibAopProxy类,通过配置Enhancer生成代理对象。Cglib则是通过构建拦截器实现的,实现MethodInterceptor接口,重写intercept方法实现方法增强。
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
}
try {
Class> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class> proxySuperClass = rootClass;
if (ClassUtils.isCglibProxyClass(rootClass)) {
proxySuperClass = rootClass.getSuperclass();
Class>[] additionalInterfaces = rootClass.getInterfaces();
for (Class> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// 验证Class
validateClassIfNecessary(proxySuperClass, classLoader);
// 配置Enhancer
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
//创建拦截器链
Callback[] callbacks = getCallbacks(rootClass);
Class>[] types = new Class>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// 生成代理类,创建代理对象
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
Spring AOP生成AOP代理对象流程
参考书籍:《Spring源码深度解析》