Spring aop解析(2)2018-08-13

接着上一节:Spring aop(1)开篇的测试类分析:

public class TestAop {
    public static void main(String[] args) {
        //手工创建一个实例(Target)
        ProxyService aspectJService = new ProxyServiceImpl();
        //使用AspectJ语法 自动创建代理对象
        AspectJProxyFactory aspectJProxyFactory = new AspectJProxyFactory(aspectJService);
        //添加切面和通知类
        aspectJProxyFactory.addAspect(AopAdviceConfig.class);
        //创建代理对象
        ProxyService proxyService = aspectJProxyFactory.getProxy();
        //进行方法调用
        proxyService.testProxy();
    }
}

从测试的代码可以看出,这段代码的重点是AspectJProxyFactory,首先我们来看下AspectJProxyFactory的UML类图:


AspectJProxyFactory继承关系.png

我们来看看继承体系中涉及到类的作用:
a、Advisor:组合了Advice。
b、Advised:组合了Advisor和TargetSource即目标对象
c、AdvisedSupport:Advised的一个实现类。继承了ProxyConfig实现了Advised。
d、ProxyConfig:在Advised中定义了一系列的配置接口,像:是否暴露对象、是否强制使用CGlib等。ProxyConfig是对这些接口的实现,但是ProxyConfig却不是Advised的实现类
e、ProxyCreatorSupport:AdvisedSupport的子类。引用了AopProxyFactory用来创建代理对象。
f、AspectJProxyFactory:ProxyCreatorSupport的子类。用来创建代理对象。使用AspectJ语法。(ProxyFactory、ProxyFactoryBean、AspectJProxyFactory这三个类功能都是一样的,但是使用场景各不相同。)

测试类解析:

1、我们先来看看new AspectJProxyFactory(aspectJService)构造方法代码如下:

public AspectJProxyFactory(Object target) {
        //检测目标对象不能为null
        Assert.notNull(target, "Target object must not be null");
        //设置目标对象的所有的接口 
        this.setInterfaces(ClassUtils.getAllInterfaces(target));
        //设置目标对象
        this.setTarget(target);
    }

2、接着我们来看看aspectJProxyFactory.addAspect(AopAdviceConfig.class):

 public void addAspect(Class aspectClass) {
        //全限定类名
        String aspectName = aspectClass.getName();
        //根据切面对象创建切面元数据类
        AspectMetadata am = this.createAspectMetadata(aspectClass, aspectName);
        //根据传入的切面类创建元数据 切面class实例 将切面实例封装为切面实例工厂
        MetadataAwareAspectInstanceFactory instanceFactory = this.createAspectInstanceFactory(am, aspectClass, aspectName);
        //从切面实例工厂中获取Advisor。
        this.addAdvisorsFromAspectInstanceFactory(instanceFactory);
    }

上面的代码分别执行了:this.createAspectMetadata、this.createAspectInstanceFactory、this.addAdvisorsFromAspectInstanceFactory这三个方法,我们分别来看下:

2.1: this.createAspectMetadata

a、我们来先看看那元数据的存储基本信息:

/**
  * AspectMetadata 切面元数据类
  */
public class AspectMetadata implements Serializable {

    /**
    * 切面的名字 可能是类的全限定类名 也可能是Spring容器中bean的名字
    */
    private final String aspectName;

    /**
    * 切面类 指带有切面注解的类
    */
    private final Class aspectClass;
    /**
    * 类的类型 这个是AspectJ中定义的类  存储了aspectClass类的类相关信息
    * 实现类为 AjTypeImpl
    */
    private transient AjType ajType;

    /**
    * Spring AOP 中的切点表达式
    */
    private final Pointcut perClausePointcut;
}

AspectMetadata这个类中主要存储了切面类的名字、切面类对象和AspectJ中定义的存储切面类Class对象的类以及SpringAOP中的切点表达式。

b、createAspectMetadata方法:

 private AspectMetadata createAspectMetadata(Class aspectClass, String aspectName) {
        //直接调用 AspectMetadata的构造函数 
        AspectMetadata am = new AspectMetadata(aspectClass, aspectName);
        //这里判断我们传入的切面类是不是切面很简单,即判断切面类上是否存在@Aspect注解。
        if (!am.getAjType().isAspect()) {
            throw new IllegalArgumentException("Class [" + aspectClass.getName() + "] is not a valid aspect type");
        }
        return am;
    }

c、接着看看AspectMetadata的构造方法:

public AspectMetadata(Class aspectClass, String aspectName) {
        //传入的切面类名直接赋值
        this.aspectName = aspectName;
        Class currClass = aspectClass;

        AjType ajType;
        //这里循环查找 带有Aspect的类,一直找到父类为Object
        for(ajType = null; currClass != Object.class; currClass = currClass.getSuperclass()) {
            AjType ajTypeToCheck = AjTypeSystem.getAjType(currClass);
            if (ajTypeToCheck.isAspect()) {
                //这里的AjType所持有的aspectClass为带有@Aspect注解的类。
                ajType = ajTypeToCheck;
                break;
            }
        }

        if (ajType == null) {
            throw new IllegalArgumentException("Class '" + aspectClass.getName() + "' is not an @AspectJ aspect");
        } else if (ajType.getDeclarePrecedence().length > 0) {
            throw new IllegalArgumentException("DeclarePrecendence not presently supported in Spring AOP");
        } else {
            this.aspectClass = ajType.getJavaClass();
            this.ajType = ajType;
            switch(this.ajType.getPerClause().getKind()) {
            //perClausePointcut切点表达式初始化
            //正常我们的Aspect类 都是SINGLETON  其他类型还不知道是什么
            case SINGLETON:
                this.perClausePointcut = Pointcut.TRUE;
                return;
            case PERTARGET:
            case PERTHIS:
                AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
                ajexp.setLocation(aspectClass.getName());
                ajexp.setExpression(this.findPerClause(aspectClass));
                ajexp.setPointcutDeclarationScope(aspectClass);
                this.perClausePointcut = ajexp;
                return;
            case PERTYPEWITHIN:
                this.perClausePointcut = new ComposablePointcut(new TypePatternClassFilter(this.findPerClause(aspectClass)));
                return;
            default:
                throw new AopConfigException("PerClause " + ajType.getPerClause().getKind() + " not supported by Spring AOP for " + aspectClass);
            }
        }
    }

2.2: this.createAspectInstanceFactory

a、我们在看createAspectInstanceFactory这个方法的代码:

 private MetadataAwareAspectInstanceFactory createAspectInstanceFactory(AspectMetadata am, Class aspectClass, String aspectName) {
        Object instanceFactory;
        //我们在使用 @Aspect注解的时候都是直接在类上添加@Aspect注解所以以下条件会成立
        if (am.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
             //根据传入的切面类创建 切面对象 是一个单例 要求有无参构造函数
            Object instance = this.getSingletonAspectInstance(aspectClass);
            instanceFactory = new SingletonMetadataAwareAspectInstanceFactory(instance, aspectName);
        } else {
            //创建一个 SimpleMetadataAwareAspectInstanceFactory
            instanceFactory = new SimpleMetadataAwareAspectInstanceFactory(aspectClass, aspectName);
        }

        return (MetadataAwareAspectInstanceFactory)instanceFactory;
    }

今天先到这里。。。。

你可能感兴趣的:(Spring aop解析(2)2018-08-13)