前言

简单示例

  • 创建切面类ServiceAspectj,这个方法用于定义切面,功能是打印方法的执行前的输入参数及输出结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Slf4j
@Aspect
@Component
public class ServiceAspectj {

@Pointcut(value = "execution(* org.springframework.iframe.service..*(..))")
public void pointcut() {

}

@Around("pointcut()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
String className = pjp.getSignature().getDeclaringType().getSimpleName();
String methodName = pjp.getSignature().getName();

log.info("=> [request method: {}#{}]",className, methodName);
log.info("=> [request body: {}]", JSONObject.toJSONString(pjp.getArgs()));

Object result = pjp.proceed();

log.info("=< [response method: {}#{}]",className, methodName);
log.info("=< [response result: {} ]", JSONObject.toJSONString(result));
return result;
}

}
  • 需要切的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public interface UserService {

User findUserByName(String userName);

}


@Service
public class UserServiceImpl implements UserService {

@Autowired
User user;

@Autowired
private RoleService roleService;

@Override
public User findUserByName(String userName) {
User user = new User(userName,18);
//Role role = roleService.findRoleByUserName(userName);
user.setRole(new Role());
return user;
}

}
  • Spring 配置文件 beans/bean.xml 添加<aop:aspectj-autoproxy/>配置,开启AOP开关
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">


<bean class="org.springframework.iframe.entity.User">
<property name="userName" value="shop"/>
</bean>

<!-- ComponentScanBeanDefinitionParser-->
<context:component-scan base-package = "org.springframework.iframe.*"/>

<aop:aspectj-autoproxy/>

</beans>
  • 测试类及测试结果
1
2
3
4
5
6
7
@Test
public void test1 () {
ClassPathXmlApplicationContext xmlApplicationContext = new ClassPathXmlApplicationContext("beans/bean.xml");
UserService userService = xmlApplicationContext.getBean(UserService.class);
User user1 = userService.findUserByName("sd");
log.info("user1:{}", user1);
}
1
2
3
4
11:12:06,216 [INFO ] [org.springframework.iframe.aop.ServiceAspectj] - => [request method: UserService#findUserByName]
11:12:06,307 [INFO ] [org.springframework.iframe.aop.ServiceAspectj] - => [request body: ["sd"]]
11:12:06,307 [INFO ] [org.springframework.iframe.aop.ServiceAspectj] - =< [response method: UserService#findUserByName]
11:12:06,372 [INFO ] [org.springframework.iframe.aop.ServiceAspectj] - =< [response result: {"age":18,"role":{},"userName":"sd"} ]
  • 从上面的例子可以看到已经实现了这个功能,那么是怎么设计呢?

    • 首先我们知道AOP是实现横切逻辑的增强,比如在方法执行前额外做一些事,方法执行后额外做一些事
    • 那我们是不是需要在一个地方定义好什么人在什么时候做什么事情,ServiceAspectj切面类就是做这个事
      • 什么人:execution(* org.springframework.iframe.service..*(..)) 这里定义了这个包下的所有方法,这些方法就是这些人
      • 什么时候:@Around注解是环绕的意思,也就是做完正常工作之前和之后做一些额外的事情
      • 做什么事情:Object doAround(ProceedingJoinPoint pjp)这个方法就是定义了具体做什么事(打印报告)
    • 上面只是些做了些规划书,还没真正起作用,那么这就需要包工头根据规划书来统一规划了,那些人需要做这些事,那些人不需要做这些事
    • 确认了那些人需要做这些事之后就是通知这些人需要多做一些事了,那么这些人就会执行打印报告的操作
  • 那么Spring究竟是如何实现AOP的呢,以后的几个章节将介绍着一块

解析

  • beans/bean.xml 配置开启AOP开关
1
2
3
4
5
6
7
8
9
10
11
// 默认标签
<bean class="org.springframework.iframe.entity.User">
<property name="userName" value="shop"/>
</bean>

// 自定义标签
<!-- ComponentScanBeanDefinitionParser-->
<context:component-scan base-package = "org.springframework.iframe.*"/>

// 自定义标签
<aop:aspectj-autoproxy/>
  • 关注上面配置文件 beans/bean.xml 中的 <aop:aspectj-autoproxy/>配置,之前的Spring系列(五)Document读取器BeanDefinitionDocumentReader章节就介绍了Spring的配置文件分为默认标签的解析及自定义标签的解析,我们现在这个<aop:aspectj-autoproxy/>配置和之前扫包的<context:component-scan配置都属于自定义标签

    • 回顾

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      /**
      * Parse the elements at the root level in the document:
      * "import", "alias", "bean".
      * @param root the DOM root element of the document
      */
      protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
      // 如果是默认命名空间 xmlns="http://www.springframework.org/schema/beans"
      if (delegate.isDefaultNamespace(root)) {
      NodeList nl = root.getChildNodes();
      for (int i = 0; i < nl.getLength(); i++) {
      Node node = nl.item(i);
      if (node instanceof Element) {
      Element ele = (Element) node;
      // 默认标签解析 如<bean class=""/>
      if (delegate.isDefaultNamespace(ele)) {
      parseDefaultElement(ele, delegate);
      }
      else { // 自定义标签解析 如:<context:component-scan base-package = "*"/>
      delegate.parseCustomElement(ele);
      }
      }
      }
      }
      else {// 自定义标签解析
      delegate.parseCustomElement(root);
      }
      }
    • 进入自定义标签解析方法delegate.parseCustomElement(root);

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      public BeanDefinition parseCustomElement(Element ele) {
      return parseCustomElement(ele, null);
      }

      public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
      // 获取xml配置文件中的命名空间http://www.springframework.org/schema/aop
      String namespaceUri = getNamespaceURI(ele);
      // 根据命名空间找到命名空间处理类AopNamespaceHandler
      NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
      if (handler == null) {
      error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
      return null;
      }
      // 解析命名空间支持的标签
      return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
      }
    • 这里有个NamespaceHandler这个接口是命名空间处理器,它可以根据需求自己来处理我们设置的标签元素。 主要功能是 通过Element标签找到对于的BeanDefinitionParser,找到之后然后调用BeanDefinitionParser接口的parse方法来解析

      • NamespaceHandler接口
        • 命名空间处理器,我们就可以根据需求自己来处理我们设置的标签元素。
        • 可能需要配置如<aop:config />这样的标签, 在配置这个标签之前,通常我们需要在xml中引入这个aop所在的命名空间,xmlns:aop="http://www.springframework.org/schema/aop
        • 只有通过配置aop的命名空间才会找到AOP标签的处理器org.springframework.aop.config.AopNamespaceHandler,在AOPjar中的spring.handlers配置文件中配置了命名空间和命名空间处理器之间的关系。
          1
          http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler
    • 比如我们这里是<aop:aspectj-autoproxy/>标签,所以得到的命名空间处理类是AopNamespaceHandler,那么是怎么得到的呢,关注this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);可以看到传入了一个namespaceUri

      • 这里是进入到DefaultNamespaceHandlerResolver#resolve方法,可以看到先是调用了getHandlerMappings() 方法读取spring.handlers配置的命名空间的对应关系,保存到了Map<String, Object> handlerMappings中,然后就是调用NamespaceHandler接口的init()方法注册解析类

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        49
        50
        51
        52
        53
        54
        55
        56
        57
        58
        59
        60
        61
        62
        63
        64
        65
        66
        67
        68
        69
        /**
        * 注册handlerMappings
        *
        * Locate the {@link NamespaceHandler} for the supplied namespace URI
        * from the configured mappings.
        * @param namespaceUri the relevant namespace URI
        * @return the located {@link NamespaceHandler}, or {@code null} if none found
        */
        @Override
        public NamespaceHandler resolve(String namespaceUri) {
        Map<String, Object> handlerMappings = getHandlerMappings();
        Object handlerOrClassName = handlerMappings.get(namespaceUri);
        if (handlerOrClassName == null) {
        return null;
        }
        else if (handlerOrClassName instanceof NamespaceHandler) {
        return (NamespaceHandler) handlerOrClassName;
        }
        else {
        String className = (String) handlerOrClassName;
        try {
        Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
        if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
        throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
        "] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
        }
        // init方法
        NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
        namespaceHandler.init();
        handlerMappings.put(namespaceUri, namespaceHandler);
        return namespaceHandler;
        }
        catch (ClassNotFoundException ex) {
        throw new FatalBeanException("NamespaceHandler class [" + className + "] for namespace [" +
        namespaceUri + "] not found", ex);
        }
        catch (LinkageError err) {
        throw new FatalBeanException("Invalid NamespaceHandler class [" + className + "] for namespace [" +
        namespaceUri + "]: problem with handler class file or dependent class", err);
        }
        }
        }
        /**
        * Load the specified NamespaceHandler mappings lazily.
        */
        private Map<String, Object> getHandlerMappings() {
        if (this.handlerMappings == null) {
        synchronized (this) {
        if (this.handlerMappings == null) {
        try {
        // 在 META-INF/spring.handlers配置文件中有配置对应关系
        Properties mappings = PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
        if (logger.isDebugEnabled()) {
        logger.debug("Loaded NamespaceHandler mappings: " + mappings);
        }
        Map<String, Object> handlerMappings = new ConcurrentHashMap<String, Object>(mappings.size());
        CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
        // 赋值到 Map<String, Object> handlerMappings中
        this.handlerMappings = handlerMappings;
        }
        catch (IOException ex) {
        throw new IllegalStateException(
        "Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex);
        }
        }
        }
        }
        return this.handlerMappings;
        }
      • 关注namespaceHandler.init();上下几行代码,这里有执行init()方法,下面的逻辑会调用,这个方法是注册标签与相应解析类对应关系的方法

    • AopNamespaceHandler.java

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      public class AopNamespaceHandler extends NamespaceHandlerSupport {

      /**
      * Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
      * '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
      * and '{@code scoped-proxy}' tags.
      */
      @Override
      public void init() {
      // In 2.0 XSD as well as in 2.1 XSD.
      registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
      registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
      registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

      // Only in 2.0 XSD: moved to context namespace as of 2.1
      registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
      }
      }
    • 关注registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());这行代码这里注册了标签命名与对应解析类的对应关系,并存放在Map<String, BeanDefinitionParser> parsers 对象中,所以现在

      1
      2
      3
      4
      5
      private final Map<String, BeanDefinitionParser> parsers = new HashMap<String, BeanDefinitionParser>();  

      protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) {
      this.parsers.put(elementName, parser);
      }

解析配置文件

  • 上面的步骤已经得到了AopNamespaceHandler,然后就是进入handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); 方法开始解析,可以看到逻辑很简单,就是在Map<String, BeanDefinitionParser> parsersget相应的解析类并调用其parse方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* 先找到对应的BeanDefinitionParser 然后执行parse(element, parserContext)方法
* Parses the supplied {@link Element} by delegating to the {@link BeanDefinitionParser} that is
* registered for that {@link Element}.
*/
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
return findParserForElement(element, parserContext).parse(element, parserContext);
}

/**
* 根据标签名得到相应的解析类,NamespaceHandler这里起到了一个中介的作用
* {@link parsers} Map<String, BeanDefinitionParser> 存放着所有的解析类,这个
*
* Locates the {@link BeanDefinitionParser} from the register implementations using
* the local name of the supplied {@link Element}.
*/
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
String localName = parserContext.getDelegate().getLocalName(element);
BeanDefinitionParser parser = this.parsers.get(localName);
if (parser == null) {
parserContext.getReaderContext().fatal(
"Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
}
return parser;
}
  • 我们这里<aop:aspectj-autoproxy/>标签得到的是AspectJAutoProxyBeanDefinitionParser解析类

AspectJAutoProxyBeanDefinitionParser

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {

@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 注册 AnnotationAwareAspectJAutoProxyCreator AOP的实现基本上是靠这个类来完成的
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
// 对于注解中子类的处理
extendBeanDefinition(element, parserContext);
return null;
}

private void extendBeanDefinition(Element element, ParserContext parserContext) {
BeanDefinition beanDef =
parserContext.getRegistry().getBeanDefinition(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);
if (element.hasChildNodes()) {
addIncludePatterns(element, parserContext, beanDef);
}
}

private void addIncludePatterns(Element element, ParserContext parserContext, BeanDefinition beanDef) {
ManagedList<TypedStringValue> includePatterns = new ManagedList<TypedStringValue>();
NodeList childNodes = element.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node node = childNodes.item(i);
if (node instanceof Element) {
Element includeElement = (Element) node;
TypedStringValue valueHolder = new TypedStringValue(includeElement.getAttribute("name"));
valueHolder.setSource(parserContext.extractSource(includeElement));
includePatterns.add(valueHolder);
}
}
if (!includePatterns.isEmpty()) {
includePatterns.setSource(parserContext.extractSource(element));
beanDef.getPropertyValues().add("includePatterns", includePatterns);
}
}

}
  • 关注parse方法,可以看到主要逻辑是注册了AnnotationAwareAspectJAutoProxyCreator这个bean
1
2
3
4
5
6
7
8
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 注册 AnnotationAwareAspectJAutoProxyCreator 对应AOP的实现基本上是靠这个类来完成的
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
// 对于注解中子类的处理
extendBeanDefinition(element, parserContext);
return null;
}
  • AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);方法这里是注册了AnnotationAwareAspectJAutoProxyCreator这个beanRootBeanDefinition beanDefinition = new RootBeanDefinition(cls);这里就把AnnotationAwareAspectJAutoProxyCreator.classBeanDefinition绑定在一起了,registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);方法是将BeanDefinition注册到BeanFactory中了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
// 关键逻辑 注册或升级AutoProxyCreator定义为beanName为org.springframework.aop.config.internalAutoProxyCreator
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
// 对于proxy-target-class(强制使用CGLIB)以及expose-proxy属性的处理
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
// 注册组件并通知,便于监听器做进一步处理
registerComponentIfNecessary(beanDefinition, parserContext);
}


// AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
// 如果已经存在了自动代理创建器且存在的自动代理创建器与现在的不一致那么需要根据优先级来判断到底需要使用哪个
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) {
// 改变bean最重要的就是改变bean所对应的className属性
apcDefinition.setBeanClassName(cls.getName());
}
}
// 如果已经存在自动代理创建器并且与将要创建的一致,那么无需再次创建
return null;
}
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;
}
  • 处理proxy-target-class属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) {
if (sourceElement != null) {
// 对proxy-target-class属性的处理 JDK动态代理或者CGLIB
boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
if (proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
// 对expose-proxy属性的处理
boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
if (exposeProxy) {
// 强制使用的过程其实也是一个属性设置的过程
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}

ConfigBeanDefinitionParser

  • ConfigBeanDefinitionParser用于解析<aop:config>标签,这种方法是Spring之前版本定义增强切面的方法,不过现在都是使用@AspectJ注解的形式来定义了,所以暂不细究
1
2
3
4
5
6
7
8
9
10
<aop:config proxy-target-class="true">
<!--使用<aop:aspect>元素标签定义切面, 其内部可以定义多个增强-->
<aop:aspect ref="adviceMethods">
<aop:after method="afterExecution" pointcut="execution(* com.aop.learn.service.*.*(..))"/>
</aop:aspect>
</aop:config>

<!--adviceMethods bean, 该bean是增强方法所在的类-->
<bean id="adviceMethods" class="com.aop.learn.advice.UserAdvice"/>
<bean id="userService" class="com.aop.learn.service.impl.UserServiceImpl"/>
  • ConfigBeanDefinitionParser 类成员及parse方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
class ConfigBeanDefinitionParser implements BeanDefinitionParser {

private static final String ASPECT = "aspect";
private static final String EXPRESSION = "expression";
private static final String ID = "id";
private static final String POINTCUT = "pointcut";
private static final String ADVICE_BEAN_NAME = "adviceBeanName";
private static final String ADVISOR = "advisor";
private static final String ADVICE_REF = "advice-ref";
private static final String POINTCUT_REF = "pointcut-ref";
private static final String REF = "ref";
private static final String BEFORE = "before";
private static final String DECLARE_PARENTS = "declare-parents";
private static final String TYPE_PATTERN = "types-matching";
private static final String DEFAULT_IMPL = "default-impl";
private static final String DELEGATE_REF = "delegate-ref";
private static final String IMPLEMENT_INTERFACE = "implement-interface";
private static final String AFTER = "after";
private static final String AFTER_RETURNING_ELEMENT = "after-returning";
private static final String AFTER_THROWING_ELEMENT = "after-throwing";
private static final String AROUND = "around";
private static final String RETURNING = "returning";
private static final String RETURNING_PROPERTY = "returningName";
private static final String THROWING = "throwing";
private static final String THROWING_PROPERTY = "throwingName";
private static final String ARG_NAMES = "arg-names";
private static final String ARG_NAMES_PROPERTY = "argumentNames";
private static final String ASPECT_NAME_PROPERTY = "aspectName";
private static final String DECLARATION_ORDER_PROPERTY = "declarationOrder";
private static final String ORDER_PROPERTY = "order";
private static final int METHOD_INDEX = 0;
private static final int POINTCUT_INDEX = 1;
private static final int ASPECT_INSTANCE_FACTORY_INDEX = 2;

private ParseState parseState = new ParseState();


@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
CompositeComponentDefinition compositeDef =
new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);

configureAutoProxyCreator(parserContext, element);

List<Element> childElts = DomUtils.getChildElements(element);
for (Element elt: childElts) {
String localName = parserContext.getDelegate().getLocalName(elt);
if (POINTCUT.equals(localName)) {
parsePointcut(elt, parserContext);
}
else if (ADVISOR.equals(localName)) {
parseAdvisor(elt, parserContext);
}
else if (ASPECT.equals(localName)) {
parseAspect(elt, parserContext);
}
}

parserContext.popAndRegisterContainingComponent();
return null;
}

总结

  • Spring中如果是用xml的方式配置Spring如果需要使用AOP功能,就需要在配置文件中添加<aop:aspectj-autoproxy/>属性,这个是打开AOP功能的开关,这是标签是自定义标签所以具体的解析工作是给AspectJAutoProxyBeanDefinitionParser来完成的,那么Spring是怎么知道这个<aop:aspectj-autoproxy/>由这个类来解析的呢,NamespaceHandler这个接口设计就发挥作用了,aop对应的命名空间处理器是AopNamespaceHandler(对应关系在aop的炸包里的META-INF/spring.handlers里设置),AopNamespaceHandler里面有配置(init方法)aspectj-autoproxy标签对应的解析类是AspectJAutoProxyBeanDefinitionParser
  • <aop:aspectj-autoproxy/> 的最终结果是注册AnnotationAwareAspectJAutoProxyCreator 这个bean,这个类用于创建AOP的代理类

参考

  • 《Spring 源码深度解析》