Spring源码分析之AOP

开发者 2024-9-28 22:27:33 151 0 来自 中国
AOP是什么

面向切面的步调操持(Aspect-oriented programming,AOP,又译作面向方面的步调操持剖面导向步调操持),是盘算机科学中的一种步调操持头脑,旨在将横切关注点与业务主体举行进一步分离,以提高步调代码的模块化程度。通过在现有代码根本上增长额外的关照(Advice)机制,能够对被声明为“切点(Pointcut)”的代码块举行同一管理与装饰。
怎么在Spring里利用AOP

在Spring里,AOP通过EnableAspectJAutoProxy注解开启。默认环境下,Spring会通过AopAutoConfiguration自动引入这个注解
@Configuration(proxyBeanMethods = false)@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)public class AopAutoConfiguration {    @Configuration(proxyBeanMethods = false)    @ConditionalOnClass(Advice.class)    static class AspectJAutoProxyingConfiguration {        @Configuration(proxyBeanMethods = false)        @EnableAspectJAutoProxy(proxyTargetClass = false)        @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false")        static class JdkDynamicAutoProxyConfiguration {        }        @Configuration(proxyBeanMethods = false)        @EnableAspectJAutoProxy(proxyTargetClass = true)        @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",                matchIfMissing = true)        static class CglibAutoProxyConfiguration {        }    }}可以看到,假如我们不自动设置spring.aop.auto=false。那么Spring默认会启用AOP。接下来,我们可以通过在类上标注Aspect即可利用AOP
package org.example.aspect;@Aspect@Componentpublic class SampleAspect {    @Pointcut("execution(* org.example.xxx.*.*(..))")    private void executionPointcut() {    }    @After(value = "executionPointcut()")    public void doAfter() {    }}源码分析

1. AOP初始化

1.1 初始化AspectJAutoProxyRegistrar

EnableAspectJAutoProxy通过Import注解引入了AspectJAutoProxyRegistrar
@Import(AspectJAutoProxyRegistrar.class)public @interface EnableAspectJAutoProxy {}AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar,Spring在初始化AopAutoConfiguration时把全部通过Import注解引入的ImportBeanDefinitionRegistrar实现类拿出来举行初始化,并调用其registerBeanDefinitions函数
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {    @Override    public void registerBeanDefinitions(            AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);}1.2 初始化AnnotationAwareAspectJAutoProxyCreator

AspectJAutoProxyRegistrar 则在registerBeanDefinitions注册了一个AnnotationAwareAspectJAutoProxyCreator的BeanDefinition
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(            BeanDefinitionRegistry registry, @Nullable Object source) {        return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);    }AnnotationAwareAspectJAutoProxyCreator实现了BeanPostProcessor,Spring会在初始化平凡Bean之前初始化全部BeanPostProcessor。
public abstract class AbstractApplicationContext extends DefaultResourceLoader        implements ConfigurableApplicationContext {        public void refresh() throws BeansException, IllegalStateException {                    // 初始化BeanProcessor来拦截Bean的创建                    registerBeanPostProcessors(beanFactory);                    // 初始化全部剩下的非懒加载的Bean,好比我们写的Service                    finishBeanFactoryInitialization(beanFactory);        }}1.3 初始化切面方法跟切点

另外,AnnotationAwareAspectJAutoProxyCreator实现了InstantiationAwareBeanPostProcessor,Spring 会在Bean创建时调用其postProcessBeforeInstantiation方法对Bean举行处置处罚。
在第一次调用该方法时,AnnotationAwareAspectJAutoProxyCreator会初始化切面
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport        implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {    @Override    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {        Object cacheKey = getCacheKey(beanClass, beanName);        if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {            //判定当前BeanName对应的Bean是否应该被署理            //并将判定效果生存下来,克制后续的后处置处罚方法重复盘算            //在第一次判定时,会在shouldSkip里扫描全部Bean举行切面初始化            if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {                this.advisedBeans.put(cacheKey, Boolean.FALSE);                return null;            }        }        //假如为AbstractAutoProxyCreator注入了自界说的TargetSourceCreator        //则通过TargetSourceCreator创建的Bean都被被AOP署理        //TargetSourceCreator默以为空        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;    }}切面初始化
public class BeanFactoryAspectJAdvisorsBuilder {        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<>();                            //拿到容器里全部的beanName                            String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(                                    this.beanFactory, Object.class, true, false);                            for (String beanName : beanNames) {                                Class<?> beanType = this.beanFactory.getType(beanName, false);                                //判定类上是否标注Aspect,以及判定该class是否已经被代码式的Aspectj处置处罚过                                if (this.advisorFactory.isAspect(beanType)) {                                    aspectNames.add(beanName);                                    AspectMetadata amd = new AspectMetadata(beanType, beanName);                                    MetadataAwareAspectInstanceFactory factory =                                                new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);                                        //从类中拿到全部带有Before、Around等注解的方法,                                        //将这些方法包装成MethodInterceptor放入Advisor,MethodInterceptor#invoke为增强方法的调用入口                                        //将Advisor排好次序构成List返回                                        List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);                                        this.advisorsCache.put(beanName, classAdvisors);                                        advisors.addAll(classAdvisors);                                }                            }                            this.aspectBeanNames = aspectNames;                            return advisors;                        }                    }                }            }}Advisor排序
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {        private static final Comparator<Method> adviceMethodComparator;        static {            Comparator<Method> adviceKindComparator = new ConvertingComparator<>(                    //按照注解次序设置方法对应的advisor的次序                    //在AspectJAfterAdvice里,会先将哀求继承向拦截器链后传播,                    //对增强方法的调用是在背面的finnaly块里。以是这里的After次序纵然在AfterReturning前面也没关系                    //另外,由于在finnly块里触发,以是纵然后续的调用抛出了未捕捉的非常,After指定的增强方法也会被实行                    new InstanceComparator<>(                            Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),                    (Converter<Method, Annotation>) method -> {                            //假如方法上没有标注上面的几个注解,则返回null,null会排在末了                        AspectJAnnotation<?> ann = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);                        return (ann != null ? ann.getAnnotation() : null);                    });            Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);            adviceMethodComparator = adviceKindComparator.thenComparing(methodNameComparator);        }}判定method是否属于切面方法
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {        public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,                int declarationOrderInAspect, String aspectName) {                //获取切点信息,假如candidateAdviceMethod不是切面方法,则返回null                AspectJExpressionPointcut expressionPointcut = getPointcut(                        candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());                if (expressionPointcut == null) {                    return null;                }                return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,                        this, aspectInstanceFactory, declarationOrderInAspect, aspectName);        }           private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {                //在方法上查找Aspectj的干系注解(Around、After等)                AspectJAnnotation<?> aspectJAnnotation =                        AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);                if (aspectJAnnotation == null) {                    return null;                }                ...        }}2. 天生署理对象

AbstractAutoProxyCreator实现了BeanPostProcessor,在创建Bean时,Spring会调用AbstractAutoProxyCreator#postProcessAfterInitialization对Bean举行处置处罚
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport        implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {        @Override        public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {            if (bean != null) {                Object cacheKey = getCacheKey(bean.getClass(), beanName);                if (this.earlyProxyReferences.remove(cacheKey) != bean) {                    //对bean举行包装,返回署理bean                    return wrapIfNecessary(bean, beanName, cacheKey);                }            }            return bean;        }        protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {                //假如bean有TargetSourceCreator创建,分析已经被署理过了,直接返回                if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {                    return bean;                }                //拿出缓存的检测的效果举行判定                if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {                    return bean;                }                //开端判定bean是否可以被署理                if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {                    this.advisedBeans.put(cacheKey, Boolean.FALSE);                    return bean;                }                //根据切点Point的表达式得到符合当前bean的全部advisor                //假如当前bean不在切点的指向中,则返回DO_NOT_PROXY                Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);                if (specificInterceptors != DO_NOT_PROXY) {                    this.advisedBeans.put(cacheKey, Boolean.TRUE);                    //创建署理对象,将全部advisor包装成DynamicAdvisedInterceptor,                    //其intercept方法为全部增强方法的同一入口,这个类来自Spring                    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;    }}选择署理对象的创建方式
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {          @Override        public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {            if (!NativeDetector.inNativeImage() &&                    (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {                Class<?> targetClass = config.getTargetClass();                //假如targetClass是接口范例大概是通过Proxy.getProxyClass天生的大概类名里包罗$$Lambda                //则利用JDK动态署理                if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {                    return new JdkDynamicAopProxy(config);                }                //利用cglib,ASM修改字节码的方式生产署理类                return new ObjenesisCglibAopProxy(config);            }            else {                return new JdkDynamicAopProxy(config);            }        }}3. 访问署理对象

DispatcherServlet 找到对应的实例跟方法后通过反射举行调用(前面Spring Mvc博文里已分析过),此时会遍历署理对象上的全部MethodInterceptor,
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {        public Object proceed() throws Throwable {            //假如拦截器遍历完了,则调用目标方法            if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {                return invokeJoinpoint();            }            //遍历全部增强器MethodInterceptor,            //遍历方式是在MethodInterceptor里调用MethodInvocation#proceed            //每次进入该方法,都会使currentInterceptorIndex增长1,从而告竣遍历            Object interceptorOrInterceptionAdvice =                    this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);            //调用MethodInterceptor#invoke            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);        }}增强方法实际实行的次序图

1.png 接下来看看每个增强注解对应的MethodInterceptor处置处罚类是怎么举行哀求处置处罚与转达的
1. AspectJAroundAdvice

public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {    @Override    @Nullable    public Object invoke(MethodInvocation mi) throws Throwable {        ...        ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;        ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);        JoinPointMatch jpm = getJoinPointMatch(pmi);        //调用Around对应的增强方法,并将mi传如增强方法        //mi持有了全部的拦截/增强器信息,通过Joinpoint#proceed实现哀求的转达        //以是,around增强方法里必要注意吸收Joinpont的实例并调用其proceed方法        return invokeAdviceMethod(pjp, jpm, null, null);    }}2. MethodBeforeAdviceInterceptor

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {    private final MethodBeforeAdvice advice;    public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {        Assert.notNull(advice, "Advice must not be null");        this.advice = advice;    }    @Override    @Nullable    public Object invoke(MethodInvocation mi) throws Throwable {        //调用before增强方法        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());        //向后转达        return mi.proceed();    }}3. AspectJAfterAdvice

public class AspectJAfterAdvice extends AbstractAspectJAdvice        implements MethodInterceptor, AfterAdvice, Serializable {        public AspectJAfterAdvice(                Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {            super(aspectJBeforeAdviceMethod, pointcut, aif);        }        @Override        @Nullable        public Object invoke(MethodInvocation mi) throws Throwable {            try {                //先向后转达                return mi.proceed();            }            finally {                //实行After方法                invokeAdviceMethod(getJoinPointMatch(), null, null);            }        }}4. AfterReturningAdviceInterceptor

public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {    private final AfterReturningAdvice advice;    public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {        Assert.notNull(advice, "Advice must not be null");        this.advice = advice;    }    @Override    @Nullable    public Object invoke(MethodInvocation mi) throws Throwable {        //向后转达        Object retVal = mi.proceed();        //调用AfterReturning方法        this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());        return retVal;    }}5. AspectJAfterThrowingAdvice

public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice        implements MethodInterceptor, AfterAdvice, Serializable {        public AspectJAfterThrowingAdvice(                Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {            super(aspectJBeforeAdviceMethod, pointcut, aif);        }        @Override        @Nullable        public Object invoke(MethodInvocation mi) throws Throwable {            try {                //向后转达                return mi.proceed();            }            catch (Throwable ex) {                //判定增强器上界说的非常范例是否匹配                if (shouldInvokeOnThrowing(ex)) {                    //调用AfterThrowing方法                    invokeAdviceMethod(getJoinPointMatch(), null, ex);                }                throw ex;            }        }        /**         * In AspectJ semantics, after throwing advice that specifies a throwing clause         * is only invoked if the thrown exception is a subtype of the given throwing type.         */        private boolean shouldInvokeOnThrowing(Throwable ex) {            return getDiscoveredThrowingType().isAssignableFrom(ex.getClass());        }}6. ExposeInvocationInterceptor

public final class ExposeInvocationInterceptor implements MethodInterceptor, PriorityOrdered, Serializable {        private static final ThreadLocal<MethodInvocation> invocation =                    new NamedThreadLocal<>("Current AOP method invocation");        @Override        @Nullable        public Object invoke(MethodInvocation mi) throws Throwable {            MethodInvocation oldInvocation = invocation.get();            //将MethodInvocation绑定到当火线程的当地变量里,            //从而实如今其他地方访问MethodInvocation            //但不发起如许做,由于AOP对于被署理对象来说应该是无感知的,不应该产生这种依赖            invocation.set(mi);            try {                return mi.proceed();            }            finally {                invocation.set(oldInvocation);            }        }}
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2025-2-6 08:59, Processed in 0.113133 second(s), 35 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表