接著上一節(jié):Spring aop(1)開篇的測試類分析:
public class TestAop {
public static void main(String[] args) {
//手工創(chuàng)建一個實例(Target)
ProxyService aspectJService = new ProxyServiceImpl();
//使用AspectJ語法 自動創(chuàng)建代理對象
AspectJProxyFactory aspectJProxyFactory = new AspectJProxyFactory(aspectJService);
//添加切面和通知類
aspectJProxyFactory.addAspect(AopAdviceConfig.class);
//創(chuàng)建代理對象
ProxyService proxyService = aspectJProxyFactory.getProxy();
//進行方法調(diào)用
proxyService.testProxy();
}
}
從測試的代碼可以看出,這段代碼的重點是AspectJProxyFactory,首先我們來看下AspectJProxyFactory的UML類圖:

我們來看看繼承體系中涉及到類的作用:
a、Advisor:組合了Advice。
b、Advised:組合了Advisor和TargetSource即目標對象
c、AdvisedSupport:Advised的一個實現(xiàn)類。繼承了ProxyConfig實現(xiàn)了Advised。
d、ProxyConfig:在Advised中定義了一系列的配置接口,像:是否暴露對象、是否強制使用CGlib等。ProxyConfig是對這些接口的實現(xiàn),但是ProxyConfig卻不是Advised的實現(xiàn)類
e、ProxyCreatorSupport:AdvisedSupport的子類。引用了AopProxyFactory用來創(chuàng)建代理對象。
f、AspectJProxyFactory:ProxyCreatorSupport的子類。用來創(chuàng)建代理對象。使用AspectJ語法。(ProxyFactory、ProxyFactoryBean、AspectJProxyFactory這三個類功能都是一樣的,但是使用場景各不相同。)
測試類解析:
1、我們先來看看new AspectJProxyFactory(aspectJService)構(gòu)造方法代碼如下:
public AspectJProxyFactory(Object target) {
//檢測目標對象不能為null
Assert.notNull(target, "Target object must not be null");
//設(shè)置目標對象的所有的接口
this.setInterfaces(ClassUtils.getAllInterfaces(target));
//設(shè)置目標對象
this.setTarget(target);
}
2、接著我們來看看aspectJProxyFactory.addAspect(AopAdviceConfig.class):
public void addAspect(Class<?> aspectClass) {
//全限定類名
String aspectName = aspectClass.getName();
//根據(jù)切面對象創(chuàng)建切面元數(shù)據(jù)類
AspectMetadata am = this.createAspectMetadata(aspectClass, aspectName);
//根據(jù)傳入的切面類創(chuàng)建元數(shù)據(jù) 切面class實例 將切面實例封裝為切面實例工廠
MetadataAwareAspectInstanceFactory instanceFactory = this.createAspectInstanceFactory(am, aspectClass, aspectName);
//從切面實例工廠中獲取Advisor。
this.addAdvisorsFromAspectInstanceFactory(instanceFactory);
}
上面的代碼分別執(zhí)行了:this.createAspectMetadata、this.createAspectInstanceFactory、this.addAdvisorsFromAspectInstanceFactory這三個方法,我們分別來看下:
2.1: this.createAspectMetadata
a、我們來先看看那元數(shù)據(jù)的存儲基本信息:
/**
* AspectMetadata 切面元數(shù)據(jù)類
*/
public class AspectMetadata implements Serializable {
/**
* 切面的名字 可能是類的全限定類名 也可能是Spring容器中bean的名字
*/
private final String aspectName;
/**
* 切面類 指帶有切面注解的類
*/
private final Class<?> aspectClass;
/**
* 類的類型 這個是AspectJ中定義的類 存儲了aspectClass類的類相關(guān)信息
* 實現(xiàn)類為 AjTypeImpl
*/
private transient AjType<?> ajType;
/**
* Spring AOP 中的切點表達式
*/
private final Pointcut perClausePointcut;
}
AspectMetadata這個類中主要存儲了切面類的名字、切面類對象和AspectJ中定義的存儲切面類Class對象的類以及SpringAOP中的切點表達式。
b、createAspectMetadata方法:
private AspectMetadata createAspectMetadata(Class<?> aspectClass, String aspectName) {
//直接調(diào)用 AspectMetadata的構(gòu)造函數(shù)
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的構(gòu)造方法:
public AspectMetadata(Class<?> aspectClass, String aspectName) {
//傳入的切面類名直接賦值
this.aspectName = aspectName;
Class<?> currClass = aspectClass;
AjType ajType;
//這里循環(huán)查找 帶有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) {
//根據(jù)傳入的切面類創(chuàng)建 切面對象 是一個單例 要求有無參構(gòu)造函數(shù)
Object instance = this.getSingletonAspectInstance(aspectClass);
instanceFactory = new SingletonMetadataAwareAspectInstanceFactory(instance, aspectName);
} else {
//創(chuàng)建一個 SimpleMetadataAwareAspectInstanceFactory
instanceFactory = new SimpleMetadataAwareAspectInstanceFactory(aspectClass, aspectName);
}
return (MetadataAwareAspectInstanceFactory)instanceFactory;
}
今天先到這里。。。。