- 前言
- 第一部分 核心实现
- 第 1 章 Spring 整体架构和环境搭建
- 第 2 章 容器的基本实现
- 第 3 章 默认标签的解析
- 第 4 章 自定义标签的解析
- 第 5 章 bean 的加载
- 第 6 章 容器的功能扩展
- 第 7 章 AOP
- 第二部分 企业应用
- 第 8 章 数据库连接 JDBC
- 第 9 章 整合 MyBatis
- 第 10 章 事务
- 第 11 章 SpringMVC
- 第 12 章 远程服务
- 第 13 章 Spring 消息
7.3.1 获取增强器
由于我们分析的是使用注解进行的 AOP,所以对于 findCandidateAdvisors 的实现其实是由 AnnotationAwareAspectJAutoProxyCreator 类完成的,我们继续跟踪 AnnotationAwareAspectJAuto ProxyCreator 的 findCandidateAdvisors 方法。
@Override
protected List<Advisor> findCandidateAdvisors() {
//当使用注解方式配置 AOP 的时候并不是丢弃了对 XML 配置的支持,
//在这里调用父类方法加载配置文件中的 AOP 声明
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
AnnotationAwareAspectJAutoProxyCreator 间接继承了 AbstractAdvisorAutoProxyCreator,在实现获取增强的方法中除了保留父类的获取配置文件中定义的增强外,同时添加了获取 Bean 的注解增强的功能,那么其实现正是由 this.aspectJAdvisorsBuilder.buildAspectJAdvisors() 来实现的。
在真正研究代码之前读者可以尝试着自己去想象一下解析思路,看看自己的实现与 Spring 是否有差别呢?或者我们一改以往的方式,先来了解函数提供的大概功能框架,读者可以在头脑中尝试实现这些功能点,看看是否有思路。
(1)获取所有 beanName,这一步骤中所有在 beanFacotry 中注册的 Bean 都会被提取出来。
(2)遍历所有 beanName,并找出声明 AspectJ 注解的类,进行进一步的处理。
(3)对标记为 AspectJ 注解的类进行增强器的提取。
(4)将提取结果加入缓存。
现在我们来看看函数实现,对 Spring 中所有的类进行分析,提取 Advisor。
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = null;
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new LinkedList<Advisor>();
aspectNames = new LinkedList<String>();
//获取所有的 beanName
String[] beanNames =BeanFactoryUtils.beanNamesForTypeIncludingAncestors
(this.beanFactory, Object.class, true, false);
//循环所有的 beanName 找出对应的增强方法
for (String beanName : beanNames) {
//不合法的 bean 则略过,由子类定义规则,默认返回 true
if (!isEligibleBean(beanName)) {
continue;
}
//获取对应的 bean 的类型
Class beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
//如果存在 Aspect 注解
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<Advisor> 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.EMPTY_LIST;
}
//记录在缓存中
List<Advisor> advisors = new LinkedList<Advisor>();
for (String aspectName : aspectNames) {
List<Advisor> 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;
}
至此,我们已经完成了 Advisor 的提取,在上面的步骤中最为重要也最为繁杂的就是增强器的获取。而这一功能委托给了 getAdvisors 方法去实现(this.advisorFactory.getAdvisors(factory))。
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) {
//获取标记为 AspectJ 的类
final Class<?> aspectClass = maaif.getAspectMetadata().getAspectClass();
//获取标记为 AspectJ 的 name
final String aspectName = maaif.getAspectMetadata().getAspectName();
//验证
validate(aspectClass);
final MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory
=new LazySingletonAspectInstanceFactoryDecorator(maaif);
final List<Advisor> advisors = new LinkedList<Advisor>();
ReflectionUtils.doWithMethods(aspectClass, new
ReflectionUtils.MethodCallback() {
public void doWith(Method method) throws IllegalArgumentException {
//声明为 Pointcut 的方法不处理
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
Advisor advisor = getAdvisor(method, lazySingletonAspectInstance
Factory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
}
});
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspect
Metadata().isLazilyInstantiated()) {
//如果寻找的增强器不为空而且又配置了增强延迟初始化那么需要在首位加入同步实例化增强器
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor (lazySingleton
AspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
//获取 DeclareParents 注解
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
函数中首先完成了对增强器的获取,包括获取注解以及根据注解生成增强的步骤,然后考虑到在配置中可能会将增强配置成延迟初始化,那么需要在首位加入同步实例化增强器以保证增强使用之前的实例化,最后是对 DeclareParents 注解的获取,下面将详细介绍一下每个步骤。
1.普通增强器的获取
普通增强器的获取逻辑通过 getAdvisor 方法实现,实现步骤包括对切点的注解的获取以及根据注解信息生成增强。
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aif,
int declarationOrderInAspect, String aspectName) {
validate(aif.getAspectMetadata().getAspectClass());
//切点信息的获取
AspectJExpressionPointcut ajexp =
getPointcut(candidateAdviceMethod, aif.getAspectMetadata().getAspectClass());
if (ajexp == null) {
return null;
}
//根据切点信息生成增强器
return new InstantiationModelAwarePointcutAdvisorImpl(
this, ajexp, aif, candidateAdviceMethod, declarationOrderInAspect,
aspectName);
}
(1)切点信息的获取。所谓获取切点信息就是指定注解的表达式信息的获取,如 @Before("test()")。
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?>
candidateAspectClass) {
//获取方法上的注解
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod
(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
//使用 AspectJExpressionPointcut 实例封装获取的信息
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0],
new Class[0]);
//提取得到的注解中的表达式如:
//@Pointcut("execution(* *.*test*(..))") 中的 execution(* *.*test*(..))
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
return ajexp;
}
protected static AspectJAnnotation findAspectJAnnotationOnMethod(Method method) {
//设置敏感的注解类
Class<? extends Annotation>[] classesToLookFor = new Class[] {
Before.class, Around.class, After.class, AfterReturning.class,
AfterThrowing.class, Pointcut.class};
for (Class<? extends Annotation> c : classesToLookFor) {
AspectJAnnotation foundAnnotation = findAnnotation(method, c);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}
//获取指定方法上的注解并使用 AspectJAnnotation 封装
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method,
Class<A> toLookFor) {
A result = AnnotationUtils.findAnnotation(method, toLookFor);
if (result != null) {
return new AspectJAnnotation<A>(result);
}
else {
return null;
}
}
(2)根据切点信息生成增强。所有的增强都由 Advisor 的实现类 InstantiationModelAware PointcutAdvisorImpl 统一封装的。
public InstantiationModelAwarePointcutAdvisorImpl(AspectJAdvisorFactory af, AspectJ
ExpressionPointcut ajexp,
MetadataAwareAspectInstanceFactory aif, Method method, int declarationOrderInAspect,
String aspectName) {
//test()
this.declaredPointcut = ajexp;
//public void test.AspectJTest.beforeTest()
this.method = method;
this.atAspectJAdvisorFactory = af;
this.aspectInstanceFactory = aif;
//0
this.declarationOrder = declarationOrderInAspect;
//test.AspectJTest
this.aspectName = aspectName;
if (aif.getAspectMetadata().isLazilyInstantiated()) {
// Static part of the pointcut is a lazy type.
Pointcut preInstantiationPointcut =
Pointcuts.union(aif.getAspectMetadata().getPerClausePointcut(),
this.declaredPointcut);
this.pointcut = new PerTargetInstantiationModelPointcut(this.declaredPointcut,
preInstantiationPointcut, aif);
this.lazy = true;
}else {
// A singleton aspect.
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
this.pointcut = declaredPointcut;
this.lazy = false;
}
}
在封装过程中只是简单地将信息封装在类的实例中,所有的信息单纯地赋值,在实例初始化的过程中还完成了对于增强器的初始化。因为不同的增强所体现的逻辑是不同的,比如 @Before(“test()”)与 @After(“test()”)标签的不同就是增强器增强的位置不同,所以就需要不同的增强器来完成不同的逻辑,而根据注解中的信息初始化对应的增强器就是在 instantiateAdvice 函数中实现的。
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
return this.atAspectJAdvisorFactory.getAdvice(
this.method, pcut, this.aspectInstanceFactory, this.declarationOrder,
this.aspectName);
}
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut ajexp,
MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect,
String aspectName) {
Class<?> candidateAspectClass = aif.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod (candidate
AdviceMethod);
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;
//根据不同的注解类型封装不同的增强器
switch (aspectJAnnotation.getAnnotationType()) {
case AtBefore:
SpringAdvice = newAspectJMethodBeforeAdvice(candidateAdviceMethod, ajexp, aif);
break;
case AtAfter:
SpringAdvice = newAspectJAfterAdvice(candidateAdviceMethod, ajexp, aif);
break;
case AtAfterReturning:
SpringAdvice = newAspectJAfterReturningAdvice(candidateAdviceMethod,
ajexp, aif);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.
getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
SpringAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
SpringAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod,
ajexp, aif);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.
getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
SpringAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
case AtAround:
SpringAdvice = new AspectJAroundAdvice(candidateAdviceMethod, ajexp, aif);
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(declarationOrderInAspect);
String[] argNames = this.parameterNameDiscoverer.getParameterNames (candidateAdvice
Method);
if (argNames != null) {
SpringAdvice.setArgumentNamesFromStringArray(argNames);
}
SpringAdvice.calculateArgumentBindings();
return SpringAdvice;
}
从函数中可以看到,Spring 会根据不同的注解生成不同的增强器,例如 AtBefore 会对应 AspectJMethodBeforeAdvice,而在 AspectJMethodBeforeAdvice 中完成了增强方法的逻辑。我们尝试分析下几个常用的增强器实现。
MethodBeforeAdviceInterceptor。
我们首先查看 MethodBeforeAdviceInterceptor 类的内部实现。
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
private MethodBeforeAdvice advice;
/**
* Create a new MethodBeforeAdviceInterceptor for the given advice.
* @param advice the MethodBeforeAdvice to wrap
*/
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
return mi.proceed();
}
}
其中的属性 MethodBeforeAdvice 代表着前置增强的 AspectJMethodBeforeAdvice,跟踪 before 方法:
public void before(Method method, Object[] args, Object target) throws Throwable {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
protected Object invokeAdviceMethod(JoinPointMatch jpMatch, Object returnValue, Throwable
ex) throws Throwable {
return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch,
returnValue, ex));
}
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
Object[] actualArgs = args;
if (this.aspectJAdviceMethod.getParameterTypes().length == 0) {
actualArgs = null;
}
try {
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
//激活增强方法
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory. getAspect
Instance(), actualArgs);
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("Mismatch on arguments to advice method [" +
this.aspectJAdviceMethod + "]; pointcut expression [" +
this.pointcut.getPointcutExpression() + "]", ex);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
invokeAdviceMethodWithGivenArgs 方法中的 aspectJAdviceMethod 正是对于前置增强的方法,在这里实现了调用。
AspectJAfterAdvice。
后置增强与前置增强有稍许不一致的地方。回顾之前讲过的前置增强,大致的结构是在拦截器链中放置 MethodBeforeAdviceInterceptor,而在 MethodBeforeAdviceInterceptor 中又放置了 AspectJMethodBeforeAdvice,并在调用 invoke 时首先串联调用。但是在后置增强的时候却不一样,没有提供中间的类,而是直接在拦截器链中使用了中间的 AspectJAfterAdvice。
public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor,
AfterAdvice {
public AspectJAfterAdvice(
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut,
AspectInstanceFactory aif) {
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
//激活增强方法
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
public boolean isBeforeAdvice() {
return false;
}
public boolean isAfterAdvice() {
return true;
}
}
2.增加同步实例化增强器
如果寻找的增强器不为空而且又配置了增强延迟初始化,那么就需要在首位加入同步实例化增强器。同步实例化增强器 SyntheticInstantiationAdvisor 如下:
protected static class SyntheticInstantiationAdvisor extends DefaultPointcutAdvisor {
public SyntheticInstantiationAdvisor(final MetadataAwareAspectInstanceFactory aif) {
super(aif.getAspectMetadata().getPerClausePointcut(), new MethodBeforeAdvice() {
//目标方法前调用,类似 @Before
public void before(Method method, Object[] args, Object target) {
//简单初始化 aspect
aif.getAspectInstance();
}
});
}
}
3.获取 DeclareParents 注解
DeclareParents 主要用于引介增强的注解形式的实现,而其实现方式与普通增强很类似,只不过使用 DeclareParentsAdvisor 对功能进行封装。
private Advisor getDeclareParentsAdvisor(Field introductionField) {
DeclareParents declareParents = (DeclareParents) introductionField.getAnnotation
(DeclareParents.class);
if (declareParents == null) {
// Not an introduction field
return null;
}
if (DeclareParents.class.equals(declareParents.defaultImpl())) {
// This is what comes back if it wasn't set. This seems bizarre...
// TODO this restriction possibly should be relaxed
throw new IllegalStateException("defaultImpl must be set on Declare
Parents");
}
return new DeclareParentsAdvisor(
introductionField.getType(), declareParents.value(), declareParents.
defaultImpl());
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论