(七)spring aop的源码学习

1.spring AOP相关的核心API接口定义

关于AOP概念
Aspect:方面    
    一个模块化的关于点
Join point:连接点 
    程序中的一个执行点(比如执行方法、执行构造器)
Advice: 通知 
    在特定的连接上的特定时机的特定行为
Pointcut:切入点
    用来匹配符合要求的连接点(用于配合通知使用,来控制在哪些连接点执行通知的行为)
Introduction:引入
    为目标增加额外的方法或者字段
Target object:目标对象
    被一个或者多个方面通知的目标对象(要增强的目标)
AOP proxy:AOP代理
    用来实现方面约定,由框架创建的代理对象
Weaving:织入
    连接方面与目标对象。
    分为编译期织入、加载期织入或者运行时织入
    Spring AOP框架与Java的AOP框架一样都是运行时织入

关于通知的类型:
Before advice:
    前置通知
After returning advice:
    正常返回通知
After throwing advice:
    异常返回通知
After (finally) advice:
    不管正常还是异常都会通知到的最终通知
Around advice:
    环绕通知

1.1. Pointcut 切入点

public interface Pointcut {

    ClassFilter getClassFilter();

    MethodMatcher getMethodMatcher();

    Pointcut TRUE = TruePointcut.INSTANCE;

}
切点点接口是由ClassFilter 与 MethodMatcher 组合而成
通过查看ClassFilter与MethodMatcher的接口定义,可以得知,ClassFilter的主要负责的是class匹配
MethodMatcher定义了静态匹配与动态匹配,动态指的是方法运行时的参数。

ClassFilter
@FunctionalInterface
public interface ClassFilter {

    boolean matches(Class<?> clazz);

    ClassFilter TRUE = TrueClassFilter.INSTANCE;

}
MethodMatcher
public interface MethodMatcher {

    boolean matches(Method method, @Nullable Class<?> targetClass);

    boolean isRuntime();

    boolean matches(Method method, @Nullable Class<?> targetClass, Object... args);

    MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;

}
因此Poincut 主要是描述了针对哪些类的\哪些方法的\哪些参数来进行AOP增强

1.2. Advice 通知

通过Advice接口可以看到它只是一个标记接口,并未定义任何方法。
所有类型的通知,都会继承自该接口。
public interface Advice {

}
接口体系

这里写图片描述

 根据接口名称 可以大致了解到,spring的几大通知类型

 1.Interceptor          拦截环绕通知
public interface Interceptor extends Advice {

}
 2.BeforeAdvice         前置通知
public interface BeforeAdvice extends Advice {

}
 3.ThrowsAdvice         异常返回通知
public interface ThrowsAdvice extends AfterAdvice {

}
 4.AfterReturning       正常返回通知
public interface AfterReturningAdvice extends AfterAdvice {

    void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable;

}
 5.IntroductionAdvice   引入通知
public interface IntroductionInterceptor extends MethodInterceptor, DynamicIntroductionAdvice {

}
再向下细分的话,就是方法的通知,还是构造器的通知.
spring中没有实现字段访问的通知,因为字段访问可以通过setter、getter方法通知来代替

1.3.Joinpoint 连接点

使用AOP各种通知时,会需要对切入对象进行最终执行,那么这个切入对象的定义就是连接点的概念。

下面查看基于方法的环绕通知MethodInterceptor的定义。
@FunctionalInterface
public interface MethodInterceptor extends Interceptor {

    Object invoke(MethodInvocation invocation) throws Throwable;

}
MethodInvocation 就是方法环绕通知的连接点。
下面继续查看连接点接口的定义

这里写图片描述

Joinpoint接口 主要定义了连接点的基本操作
1.执行
2.获取连接目标对象
3.获取连接目标
public interface Joinpoint {

    //连接点执行
    Object proceed() throws Throwable;

    //获取连目标的实例对象(this)
    Object getThis();

    //获取连目标(method、constructor...)
    AccessibleObject getStaticPart();

}
关于JoinPoin的子接口
Invocation
定义了获取可执行目标执行参数的接口
public interface Invocation extends Joinpoint {

    Object[] getArguments();

}
ConstructorInvocation
具体的关于构造器的连接点定义
Joinpoint.getStaticPart() 与 这里的getConstructor返回同样的结果,
这个接口的作用是返回值更友好,无须自行强转了
public interface ConstructorInvocation extends Invocation {

    Constructor<?> getConstructor();

}
MethodInvocation
具体的关于方法的连接点定义
Joinpoint.getStaticPart() 与 这里的getMethod返回同样的结果,
这个接口的作用是返回值更友好,无须自行强转了
public interface MethodInvocation extends Invocation {

    Method getMethod();

}

1.4.Advisor 对方面对象的包装接口

public interface Advisor {

    Advice EMPTY_ADVICE = new Advice() {};

    Advice getAdvice();

    boolean isPerInstance();

}
从接口可以看出该接口的存在的目的就是作为Advice的Holder而存在。
它有两个直接子接口,分别是:
public interface PointcutAdvisor extends Advisor {

    Pointcut getPointcut();

}
public interface IntroductionAdvisor extends Advisor, IntroductionInfo {

    ClassFilter getClassFilter();

    void validateInterfaces() throws IllegalArgumentException;

}
PointcutAdvisor定义了Advice与Pointcut组合使用的场景
IntroductionAdvisor是对引入通知实现基本定义,包括引入的接口信息,而引入通知是向某个实例中引入新的方法,因此
不存在对方法匹配的MethodMatcher,只需要匹配类ClassFilter

2.spring aop的实现

上面查看了 有关spring aop的基本概念定义的相关接口
现在对 spring aop是如果与实例进行关联织入的,进行源码查看分析。

在org.springframework.aop.config.AopNamespaceHandler定义了关于xml方式配置的有关aop namespace下的BeanDefinitionParser
public class AopNamespaceHandler extends NamespaceHandlerSupport {

    @Override
    public void init() {
        //注册负责解析<aop:config>的parser
        // In 2.0 XSD as well as in 2.1 XSD.
        registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
        //注册负责解析<aop:aspectj-autoproxy>的parser
        registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
        registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

        // Only in 2.0 XSD: moved to context namespace as of 2.1
        //注册负责解析<aop:spring-configured>的parser
        registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
    }

}
关于aop的配置,主要是配置:
1.通知
2.切入点
3.方面 即 通知 + 切入点

有了切入点就知道需要对什么目标进行aop增强,
有了通知就知道了aop增强的内容
具体的配置细节这里就不作详细查看了。
接下查看spring是怎么创建代理对象的。
class ConfigBeanDefinitionParser implements BeanDefinitionParser {
    //..略
    @Override
    @Nullable
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        //..略
        configureAutoProxyCreator(parserContext, element);
        //..略
    }
    //..略
    private void configureAutoProxyCreator(ParserContext parserContext, Element element) {
        AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element);
    }
}
在AopNamespaceUtils对ProxyCreator进行注册配置
AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary(
            parserContext.getRegistry(), parserContext.extractSource(sourceElement))
接下来查看AopConfigUtils中的registerAspectJAutoProxyCreatorIfNecessary看看到底注册的什么类
public abstract class AopConfigUtils {

    public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
            "org.springframework.aop.config.internalAutoProxyCreator";

    private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>();

    static {
        APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
        APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
        APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
    }
    //...略
    @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");
        //这里是根据上面APC_PRIORITY_LIST中当前注册类的角标 来判断的优先级
        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;
        }
        //未配置过,直接注册到registry中
        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;
    }
}
可以看到spring创建代理对象的实现主要是InfrastructureAdvisorAutoProxyCreator、AspectJAwareAdvisorAutoProxyCreator、AnnotationAwareAspectJAutoProxyCreator
而spring对aspectj的集成 只是将aspectj的表达式 与 @Aspectj相关注解进行作为aop配置信息进行了支持,实质上spring aop 都是基于的CGLIB 与 JDK的动态代理
而且只能对象交给spring管理的bean进行aop支持,对像 domain 这种不是spring管理的对象,如果想进行方面编程则需要考虑使用full aspectj 进行实现。

而上面三个Creator都继承自AbstractAdvisorAutoProxyCreator 该类主要实现获取方面实例Advisor
AbstractAdvisorAutoProxyCreator继承自AbstractAutoProxyCreator 该类主要是实现代理对象的创建
主要是拓展spring的SmartInstantiationAwareBeanPostProcessor来实现的代理对象创建
下面查看创建类的代码
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
        implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

    //...略
    //获取代理对象的类型
    @Override
    @Nullable
    public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
        if (this.proxyTypes.isEmpty()) {
            return null;
        }
        Object cacheKey = getCacheKey(beanClass, beanName);
        return this.proxyTypes.get(cacheKey);
    }
    @Override
    @Nullable
    public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }
    //对循环引用的支持,用来提供创建单例对象过程中的引用
    @Override
    public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            this.earlyProxyReferences.add(cacheKey);
        }
        return wrapIfNecessary(bean, beanName, cacheKey);
    }
    //在执行对象实例化之前判断是否满足方面来进行代理对象创建
    @Override
    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;
            }
            //如果目标本身就是AOP相关的实例则不进行代理处理
            if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return null;
            }
        }

        // 如果配置了TargetSourceCreator 则从中获取TargetSource实例进行代理创建,这样 就不必走BeanFacotry中的实例创建了
        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;
    }
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) {
        return true;
    }
    @Override
    public PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {

        return pvs;
    }
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        return bean;
    }
    //这里针对实例化完毕且初始化完成的实例,来判断是否进行代理实现
    @Override
    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;
        }
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

        // 获取对象的通知,这里是利用Advisor中的Pointcut来判断是否满足
        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;
    }
    //代理对象创建的方法
    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);
        //判断是否强制使用cglib
        if (!proxyFactory.isProxyTargetClass()) {
            if (shouldProxyTargetClass(beanClass, beanName)) {
                proxyFactory.setProxyTargetClass(true);
            }
            else {
                //如果目标类没有相应的接口,依然会选用cglib做动态代理
                evaluateProxyInterfaces(beanClass, proxyFactory);
            }
        }

        //组合通知类
        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        proxyFactory.addAdvisors(advisors);
        proxyFactory.setTargetSource(targetSource);
        customizeProxyFactory(proxyFactory);
        // 如果设置true 则表示 后面不希望被更改通知advisors
        proxyFactory.setFrozen(this.freezeProxy);
        if (advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }

        //创建代理对象
        return proxyFactory.getProxy(getProxyClassLoader());
    }
}
关于proxyFactory创建代理对象的方式,主要是根据proxyTargetClass = true / false 来判断使用
org.springframework.aop.framework.CglibAopProxy  / org.springframework.aop.framework.JdkDynamicAopProxy
内部主要是创建和配置代理对象,使对应的代理对象与 上面定义的AOP各个通知Advice 进行关联起来。


小结:
    在spring 声明式事物中, 如果调用了一个aop的普通方法 在转调事物方法,事物无效
    如果下如果调用 a.method1();则不会触发事物,这是因为虽然a对象在spring中是代理对象,在a.method1()时 关于事物的advisor 进行
    切入点判断时,方法不符合规则不会进行环绕通知开启提交事物,而在method1()方法中转调 method2时,使用的是this调用,并不是代理
    对象调用,因此不会再走代理方法。从而导致事务失效。
    class A {
        public void method1(){method2();}
        @Trasnactional
        public void method2(){..}
    }

    因此在使用spring aop过程中要切记!!!

猜你喜欢

转载自blog.csdn.net/m0_38043362/article/details/80284597
今日推荐