简单代码示例, 了解Spring AOP基于xml的基本用法
xml配置:
<?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: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/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="aopAdvice" class="org.spring.aop.parse.advice.AopAdvice"></bean>
<!-- 第一种配置方式 -->
<aop:config proxy-target-class="false">
<aop:aspect ref="aopAdvice">
<aop:pointcut expression="execution(* org.spring.aop.parse.service..*.*(..))" id="callAt"/>
<aop:around method="around" pointcut-ref="callAt"/>
<aop:before method="before" pointcut="execution(* org.spring.aop.parse.service..*.*(..))"/>
<aop:after method="after" pointcut="execution(* org.spring.aop.parse.service..*.*(..))"/>
</aop:aspect>
</aop:config>
<!--<aop:config proxy-target-class="true">
<aop:pointcut id="callAt" expression="execution(* org.spring.aop.service..*.*(..))"></aop:pointcut>
</aop:config>-->
<!-- 第二种配置方式 -->
<bean id="logAdvice" class="org.spring.aop.parse.advice.LogAdvice"></bean>
<aop:config proxy-target-class="false">
<!--<aop:pointcut id="callAt" expression="execution(* org.spring.aop.service..*.*(..))"></aop:pointcut>-->
<aop:advisor id="logAdvisor" advice-ref="logAdvice" pointcut="execution(* org.spring.aop.parse.service..*.*(..))"></aop:advisor>
<!--<aop:advisor id="logAdvisor" advice-ref="logAdvice" pointcut-ref="callAt"></aop:advisor>-->
</aop:config>
<!-- 第三种引介增强 -->
<!--<bean id="addService" class="org.spring.aop.parse.advice.AddService"/>-->
<aop:config proxy-target-class="false">
<aop:aspect ref="aopAdvice">
<aop:declare-parents types-matching="org.spring.aop.parse.service.*" implement-interface="org.spring.aop.parse.advice.IAddService" default-impl="org.spring.aop.parse.advice.AddService"/>
<!--<aop:declare-parents types-matching="org.spring.aop.parse.service.*" implement-interface="org.spring.aop.parse.advice.IAddService" delegate-ref="addService"/>-->
</aop:aspect>
</aop:config>
<bean id="userService" class="org.spring.aop.parse.service.UserService"/>
</beans>
测试代码:
package org.spring.aop.parse;
import org.spring.aop.parse.advice.IAddService;
import org.spring.aop.parse.service.IUserService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config-aop.xml");
applicationContext.start();
Object objService = applicationContext.getBean("userService");
IUserService userService = (IUserService)objService;
userService.say();
System.out.println("\n-------------对目标对象引介增强-----------------\n");
IAddService addService = (IAddService)objService;
addService.doSomething();
applicationContext.stop();
}
}
执行结果:
=======================开始从源码分析过程========================
从handler中找到标签对应的NamespaceHandler:AopNamespaceHandler
从AopNamespaceHandler中找到标签对应的BeanDefinitionParser:ConfigBeanDefinitionParser,ConfigBeanDefinitionParser就是源码第一个关键入口
ConfigBeanDefinitionParser:将xml配置转换为Advisor的BeanDefinition,在ApplicationContext的refresh()中自动调用,将BeanDefinition转为Advisor对象。
package org.springframework.aop.config;
import java.util.ArrayList;
import java.util.List;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.springframework.aop.aspectj.AspectJAfterAdvice;
import org.springframework.aop.aspectj.AspectJAfterReturningAdvice;
import org.springframework.aop.aspectj.AspectJAfterThrowingAdvice;
import org.springframework.aop.aspectj.AspectJAroundAdvice;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.aspectj.AspectJMethodBeforeAdvice;
import org.springframework.aop.aspectj.AspectJPointcutAdvisor;
import org.springframework.aop.aspectj.DeclareParentsAdvisor;
import org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanReference;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.config.RuntimeBeanNameReference;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
import org.springframework.beans.factory.parsing.ParseState;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
public 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();
/**
<bean id="logBeforeAdvice" class="org.spring.aop.config.LogBeforeAdvice"></bean>
<aop:config proxy-target-class="true">
<aop:advisor id="logBeforeAdvisor" advice-ref="logBeforeAdvice" pointcut="execution(* org.spring.aop.service..*.*(..))"></aop:advisor>
</aop:config>
注意:<aop:advisor>生成的advisor的BeanDefinition的beanClass类型是:DefaultBeanFactoryPointcutAdvisor,对应构造函数是无参构造函数
<aop:advisor>属性advice-ref对应的 advice bean 是自定义的,需要实现接口Advice
<aop:config proxy-target-class="true">
<aop:aspect ref="aopAdvice">
<aop:pointcut expression="execution(* org.spring.aop.service..*.*(..))" id="callAt"/>
<aop:around method="around" pointcut-ref="callAt"/>
<aop:before method="before" pointcut="execution(* org.spring.aop.service..*.*(..))"/>
</aop:aspect>
</aop:config>
注意:<aop:aspect>生成的advisor的BeanDefinition的beanClass类型是:AspectJPointcutAdvisor,对应构成函数AspectJPointcutAdvisor(AbstractAspectJAdvice advice)
<aop:aspect>下的每个Advice都有自己的实现
1、<aop:around>==》AspectJAroundAdvice
2、<aop:before>==》AspectJMethodBeforeAdvice
3、<aop:after>==》AspectJAfterAdvice
4、<aop:after-returning>==》AspectJAfterReturningAdvice
5、<aop:after-throwing>==》AspectJAfterThrowingAdvice
上面Advice构造函数初始化时会匹配三参构造函数:AbstractAspectJAdvice(Method aspectJAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aspectInstanceFactory)
AbstractAspectJAdvice是上面5个Advice的父类
所有的PointCut生成的BeanDefinition的beanClass类型是:AspectJExpressionPointcut
解析完成后会将生成的advisor的BeanDefinition注册到IOC容器
如果pointcut是元素<aop:pointcut>生成的BeanDefinition会注册到IOC容器;
如果pointcut是属性pointcut="execution(* org.spring.aop.service..*.*(..))"生成的BeanDefinition不会注册到IOC容器;
*/
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
CompositeComponentDefinition compositeDef =
new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
/**
* @see AspectJAwareAdvisorAutoProxyCreator
* 创建BeanDefinition,对应的beanClass为AspectJAwareAdvisorAutoProxyCreator
* 实现了后置处理器 SmartInstantiationAwareBeanPostProcessor、InstantiationAwareBeanPostProcessor、BeanPostProcessor
*
SmartInstantiationAwareBeanPostProcessor
//AbstractAutoProxyCreator#predictBeanType
Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException;
//AbstractAutoProxyCreator#determineCandidateConstructors 直接返回null
Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException;
//AbstractAutoProxyCreator#getEarlyBeanReference
Object getEarlyBeanReference(Object bean, String beanName) throws BeansException;
InstantiationAwareBeanPostProcessor
//负责创建advisor,在每个bean创建前执行,关键入口
//AbstractAutoProxyCreator#postProcessBeforeInstantiation
Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;
//AbstractAutoProxyCreator#postProcessAfterInstantiation 直接返回true
boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;
//AbstractAutoProxyCreator#postProcessPropertyValues 直接返回pvs
PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;
BeanPostProcessor
//AbstractAutoProxyCreator#postProcessBeforeInitialization 直接返回bean
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
//负责创建aop相关工作,将advisor关联到bean,在每个bean创建并初始化完成后执行,关键入口
//AbstractAutoProxyCreator#postProcessAfterInitialization
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
*
*/
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;
}
/**
* 创建BeanDefinition,对应的beanClass为AspectJAwareAdvisorAutoProxyCreator
* @see AspectJAwareAdvisorAutoProxyCreator
*
* 实现了后置处理器 SmartInstantiationAwareBeanPostProcessor--实现-》InstantiationAwareBeanPostProcessor-实现--》BeanPostProcessor
*
*/
private void configureAutoProxyCreator(ParserContext parserContext, Element element) {
AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element);
}
/**
* 解析元素<aop:pointcut/>
*
<aop:config proxy-target-class="true">
<aop:pointcut id="callAt" expression="execution(* org.spring.aop.service..*.*(..))"></aop:pointcut>
</aop:config>
* 创建Pointcut BeanDefinition,beanClass为:AspectJExpressionPointcut
* @see AspectJExpressionPointcut
* 设置beanDefinition 属性 expression
*/
private AbstractBeanDefinition parsePointcut(Element pointcutElement, ParserContext parserContext) {
String id = pointcutElement.getAttribute(ID);
String expression = pointcutElement.getAttribute(EXPRESSION);
AbstractBeanDefinition pointcutDefinition = null;
try {
this.parseState.push(new PointcutEntry(id));
//创建Pointcut BeanDefinition,beanClass为:AspectJExpressionPointcut
pointcutDefinition = createPointcutDefinition(expression);
pointcutDefinition.setSource(parserContext.extractSource(pointcutElement));
//设置Pointcut BeanDefinition的beanName为id,如果id为空,用beanClassName+递增数字
String pointcutBeanName = id;
if (StringUtils.hasText(pointcutBeanName)) {
parserContext.getRegistry().registerBeanDefinition(pointcutBeanName, pointcutDefinition);
}
else {
pointcutBeanName = parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition);
}
parserContext.registerComponent(
new PointcutComponentDefinition(pointcutBeanName, pointcutDefinition, expression));
}
finally {
this.parseState.pop();
}
return pointcutDefinition;
}
/**
* 解析元素<aop:advisor/>
*
<bean id="logBeforeAdvice" class="org.spring.aop.config.LogBeforeAdvice"></bean>
<aop:config proxy-target-class="true">
<aop:advisor id="logBeforeAdvisor" advice-ref="logBeforeAdvice" pointcut="execution(* org.spring.aop.service..*.*(..))"></aop:advisor>
</aop:config>
* 创建Advisor对应的BeanDefinition,beanClass为:DefaultBeanFactoryPointcutAdvisor
* @see DefaultBeanFactoryPointcutAdvisor
* 设置beanDefinition 属性 expression
*/
private void parseAdvisor(Element advisorElement, ParserContext parserContext) {
//创建Advisor对应的BeanDefinition,beanClass为:DefaultBeanFactoryPointcutAdvisor
AbstractBeanDefinition advisorDef = createAdvisorBeanDefinition(advisorElement, parserContext);
String id = advisorElement.getAttribute(ID);
try {
this.parseState.push(new AdvisorEntry(id));
String advisorBeanName = id;
if (StringUtils.hasText(advisorBeanName)) {
parserContext.getRegistry().registerBeanDefinition(advisorBeanName, advisorDef);
}
else {
advisorBeanName = parserContext.getReaderContext().registerWithGeneratedName(advisorDef);
}
//设置依赖的Pointcut
Object pointcut = parsePointcutProperty(advisorElement, parserContext);
if (pointcut instanceof BeanDefinition) { //pointcut,属性值为BeanDefinition,后续填充属性时,做依赖bean处理
advisorDef.getPropertyValues().add(POINTCUT, pointcut);
parserContext.registerComponent(
new AdvisorComponentDefinition(advisorBeanName, advisorDef, (BeanDefinition) pointcut));
}
else if (pointcut instanceof String) {//pointcut-ref,属性值为RuntimeBeanReference,后续填充属性时,做依赖bean处理
advisorDef.getPropertyValues().add(POINTCUT, new RuntimeBeanReference((String) pointcut));
parserContext.registerComponent(
new AdvisorComponentDefinition(advisorBeanName, advisorDef));
}
}
finally {
this.parseState.pop();
}
}
/**
* 解析元素<aop:aspect/>
*
<bean id="aopAdvice" class="org.spring.aop.aspectj.AopAdvice"></bean>
<aop:config proxy-target-class="true">
<aop:aspect ref="aopAdvice">
<aop:pointcut expression="execution(* org.spring.aop.service..*.*(..))" id="callAt"/>
<aop:around method="around" pointcut-ref="callAt"/>
<aop:before method="before" pointcut="execution(* org.spring.aop.service..*.*(..))"/>
<aop:after method="before" pointcut="execution(* org.spring.aop.service..*.*(..))"/>
</aop:aspect>
</aop:config>
*
*
* 创建Pointcut BeanDefinition,beanClass为:AspectJExpressionPointcut
* @see AspectJExpressionPointcut
* 设置beanDefinition 属性 expression AspectJPointcutAdvisor
*/
private void parseAspect(Element aspectElement, ParserContext parserContext) {
String aspectId = aspectElement.getAttribute(ID);
String aspectName = aspectElement.getAttribute(REF);
try {
this.parseState.push(new AspectEntry(aspectId, aspectName));
//存储BeanDefinition形式的PointCut
List<BeanDefinition> beanDefinitions = new ArrayList<>();
//存储BeanReference形式的PointCut 额外存储了beanReferences.add(new RuntimeBeanReference(aspectName))
List<BeanReference> beanReferences = new ArrayList<>();
//解析引介增强方式
List<Element> declareParents = DomUtils.getChildElementsByTagName(aspectElement, DECLARE_PARENTS);
for (int i = METHOD_INDEX; i < declareParents.size(); i++) {
Element declareParentsElement = declareParents.get(i);
beanDefinitions.add(parseDeclareParents(declareParentsElement, parserContext));
}
// We have to parse "advice" and all the advice kinds in one loop, to get the
// ordering semantics right.
/*
循环Advice,生成Advice和Advisor的BeanDefinition
Advice与Advisor一样对应
*/
NodeList nodeList = aspectElement.getChildNodes();
boolean adviceFoundAlready = false;
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (isAdviceNode(node, parserContext)) {
if (!adviceFoundAlready) {
adviceFoundAlready = true;
if (!StringUtils.hasText(aspectName)) {
parserContext.getReaderContext().error(
"<aspect> tag needs aspect bean reference via 'ref' attribute when declaring advices.",
aspectElement, this.parseState.snapshot());
return;
}
beanReferences.add(new RuntimeBeanReference(aspectName));
}
//生成单个Advisor的Definition
AbstractBeanDefinition advisorDefinition = parseAdvice(
aspectName, i, aspectElement, (Element) node, parserContext, beanDefinitions, beanReferences);
beanDefinitions.add(advisorDefinition);
}
}
//注册事件相关的
AspectComponentDefinition aspectComponentDefinition = createAspectComponentDefinition(
aspectElement, aspectId, beanDefinitions, beanReferences, parserContext);
parserContext.pushContainingComponent(aspectComponentDefinition);
List<Element> pointcuts = DomUtils.getChildElementsByTagName(aspectElement, POINTCUT);
for (Element pointcutElement : pointcuts) {
//解析里面的<aop:pointcut>元素
parsePointcut(pointcutElement, parserContext);
}
//注册事件相关的
parserContext.popAndRegisterContainingComponent();
}
finally {
this.parseState.pop();
}
}
//注册事件相关的
private AspectComponentDefinition createAspectComponentDefinition(
Element aspectElement, String aspectId, List<BeanDefinition> beanDefs,
List<BeanReference> beanRefs, ParserContext parserContext) {
BeanDefinition[] beanDefArray = beanDefs.toArray(new BeanDefinition[beanDefs.size()]);
BeanReference[] beanRefArray = beanRefs.toArray(new BeanReference[beanRefs.size()]);
Object source = parserContext.extractSource(aspectElement);
return new AspectComponentDefinition(aspectId, beanDefArray, beanRefArray, source);
}
/**
* 创建Pointcut对应的BeanDefinition,beanClass为:AspectJExpressionPointcut
* @see AspectJExpressionPointcut
*
* 设置beanDefinition 属性 expression
*/
protected AbstractBeanDefinition createPointcutDefinition(String expression) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(AspectJExpressionPointcut.class);
beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
beanDefinition.setSynthetic(true);
beanDefinition.getPropertyValues().add(EXPRESSION, expression);
return beanDefinition;
}
/**
* 创建Advisor对应的BeanDefinition,beanClass为:DefaultBeanFactoryPointcutAdvisor
* @see DefaultBeanFactoryPointcutAdvisor
*
* 设置beanDefinition 属性 expression
*/
private AbstractBeanDefinition createAdvisorBeanDefinition(Element advisorElement, ParserContext parserContext) {
RootBeanDefinition advisorDefinition = new RootBeanDefinition(DefaultBeanFactoryPointcutAdvisor.class);
advisorDefinition.setSource(parserContext.extractSource(advisorElement));
String adviceRef = advisorElement.getAttribute(ADVICE_REF);
if (!StringUtils.hasText(adviceRef)) {
parserContext.getReaderContext().error(
"'advice-ref' attribute contains empty value.", advisorElement, this.parseState.snapshot());
}
else { //设置依赖的Advice
advisorDefinition.getPropertyValues().add(
ADVICE_BEAN_NAME, new RuntimeBeanNameReference(adviceRef));
}
if (advisorElement.hasAttribute(ORDER_PROPERTY)) {
advisorDefinition.getPropertyValues().add(
ORDER_PROPERTY, advisorElement.getAttribute(ORDER_PROPERTY));
}
return advisorDefinition;
}
/**
* 解析pointcut或者pointcut-ref,属性不能同时出现,二者选一
* pointcut="execution(* org.spring.aop.service..*.*(..))"
* pointcut-ref="callAt"
*
* @return
*/
private Object parsePointcutProperty(Element element, ParserContext parserContext) {
if (element.hasAttribute(POINTCUT) && element.hasAttribute(POINTCUT_REF)) {
parserContext.getReaderContext().error(
"Cannot define both 'pointcut' and 'pointcut-ref' on <advisor> tag.",
element, this.parseState.snapshot());
return null;
}
else if (element.hasAttribute(POINTCUT)) { //为pointcut时,创建BeanDefinition,beanClass为:AspectJExpressionPointcut
String expression = element.getAttribute(POINTCUT);
AbstractBeanDefinition pointcutDefinition = createPointcutDefinition(expression);
pointcutDefinition.setSource(parserContext.extractSource(element));
return pointcutDefinition;
}
else if (element.hasAttribute(POINTCUT_REF)) { //为pointcut-ref时,直接返回字符串内容
String pointcutRef = element.getAttribute(POINTCUT_REF);
if (!StringUtils.hasText(pointcutRef)) {
parserContext.getReaderContext().error(
"'pointcut-ref' attribute contains empty value.", element, this.parseState.snapshot());
return null;
}
return pointcutRef;
}
else {
parserContext.getReaderContext().error(
"Must define one of 'pointcut' or 'pointcut-ref' on <advisor> tag.",
element, this.parseState.snapshot());
return null;
}
}
/*
1、创建PointCut的BeanDefinition,PointCut代表拦截点
2、创建Advice的BeanDefinition,Advice代表在哪个位置增强,around、before、after、return、throw
3、创建Advisor的BeanDefinition,持有Advice的BeanDefinition
*/
//beanDefinitions, BeanDefinition形式的PointCut
//beanReferences, BeanReference形式的PointCut
private AbstractBeanDefinition parseAdvice(
String aspectName, int order, Element aspectElement, Element adviceElement, ParserContext parserContext,
List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {
try {
this.parseState.push(new AdviceEntry(parserContext.getDelegate().getLocalName(adviceElement)));
/*
<bean id="aopAdvice" class="org.spring.aop.aspectj.AopAdvice"></bean>
<aop:config proxy-target-class="true">
<aop:aspect ref="aopAdvice">
<aop:around method="around" pointcut-ref="execution(* org.spring.aop.service..*.*(..))"/>
</aop:aspect>
</aop:config>
*/
//MethodLocatingFactoryBean主要用途是根据类名(targetBeanName)和方法名(methodName)获取Advice实例的method方法对象 AopAdvice.around()
RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class);
methodDefinition.getPropertyValues().add("targetBeanName", aspectName);
methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method"));
methodDefinition.setSynthetic(true);
//SimpleBeanFactoryAwareAspectInstanceFactory用途主要是根据aspectBeanName获取Advice的Bean实例
//<bean id="aopAdvice" class="org.spring.aop.aspectj.AopAdvice"></bean>
//将来可以查询bean==》aopAdvice
RootBeanDefinition aspectFactoryDef =
new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class);
aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName);
aspectFactoryDef.setSynthetic(true);
// 创建Advice的BeanDefinition
//AspectJAroundAdvice构造方法==>public AspectJAroundAdvice(Method aspectJAroundAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {}
//下面代码构建上述构造函数的BeanDefinition
AbstractBeanDefinition adviceDef = createAdviceDefinition(
adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef,
beanDefinitions, beanReferences);
// 创建Advisor的BeanDefinition, 构造函数参数是上面Advice的BeanDefinition
RootBeanDefinition advisorDefinition = new RootBeanDefinition(AspectJPointcutAdvisor.class);
advisorDefinition.setSource(parserContext.extractSource(adviceElement));
advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef);
if (aspectElement.hasAttribute(ORDER_PROPERTY)) {
advisorDefinition.getPropertyValues().add(
ORDER_PROPERTY, aspectElement.getAttribute(ORDER_PROPERTY));
}
// 将advisor的BeanDefinition注册进IOC容器
parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition);
return advisorDefinition;
}
finally {
this.parseState.pop();
}
}
/*
创建advice对应的BeanDefinition,
BeanDefinition的beanClass由advice元素名称决定
1、<aop:around>==》AspectJAroundAdvice
2、<aop:before>==》AspectJMethodBeforeAdvice
3、<aop:after>==》AspectJAfterAdvice
4、<aop:after-returning>==》AspectJAfterReturningAdvice
5、<aop:after-throwing>==》AspectJAfterThrowingAdvice
BeanDefinition有三个构造函数参数
第一个参数:methodDef ==> RootBeanDefinition(MethodLocatingFactoryBean.class)
有两个属性:targetBeanName对应<aop:aspect ref="aopAdvice">的ref值
methodName对应<aop:around method="around">的method值
第二个参数:pointcut
<aop:around pointcut-ref="callAt"/>类型就是RuntimeBeanReference(expression),其实最后还是AspectJExpressionPointcut
<aop:before pointcut="execution(* xxx.xxx.service..*.*(..))"/>类型就是RootBeanDefinition(AspectJExpressionPointcut)
第三个参数:aspectFactoryDef ==> RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class)
有个一个属性:aspectBeanName对应<aop:aspect ref="aopAdvice">的ref值
比如环绕advice: AspectJAroundAdvice
构造方法==>public AspectJAroundAdvice(Method aspectJAroundAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {}
*/
//beanDefinitions, BeanDefinition形式的PointCut,后面直接注册进IOC容器
//beanReferences, BeanReference形式的PointCut,后面封装成BeanDefinition注册进IOC容器
private AbstractBeanDefinition createAdviceDefinition(
Element adviceElement, ParserContext parserContext, String aspectName, int order,
RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef,
List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {
RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement, parserContext));
adviceDefinition.setSource(parserContext.extractSource(adviceElement));
adviceDefinition.getPropertyValues().add(ASPECT_NAME_PROPERTY, aspectName);
adviceDefinition.getPropertyValues().add(DECLARATION_ORDER_PROPERTY, order);
if (adviceElement.hasAttribute(RETURNING)) {
adviceDefinition.getPropertyValues().add(
RETURNING_PROPERTY, adviceElement.getAttribute(RETURNING));
}
if (adviceElement.hasAttribute(THROWING)) {
adviceDefinition.getPropertyValues().add(
THROWING_PROPERTY, adviceElement.getAttribute(THROWING));
}
if (adviceElement.hasAttribute(ARG_NAMES)) {
adviceDefinition.getPropertyValues().add(
ARG_NAMES_PROPERTY, adviceElement.getAttribute(ARG_NAMES));
}
//创建adviceDefinition的构造函数
ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues();
cav.addIndexedArgumentValue(METHOD_INDEX, methodDef);
/**
* 解析pointcut或者pointcut-ref,属性不能同时出现,二者选一
* pointcut="execution(* org.spring.aop.service..*.*(..))"
* pointcut-ref="callAt"
*/
Object pointcut = parsePointcutProperty(adviceElement, parserContext);
if (pointcut instanceof BeanDefinition) {
cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcut);
beanDefinitions.add((BeanDefinition) pointcut);
}
else if (pointcut instanceof String) {
RuntimeBeanReference pointcutRef = new RuntimeBeanReference((String) pointcut);
cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcutRef);
beanReferences.add(pointcutRef);
}
cav.addIndexedArgumentValue(ASPECT_INSTANCE_FACTORY_INDEX, aspectFactoryDef);
return adviceDefinition;
}
/*
* 根据advice元素名称获取对应的beanClass
* <aop:around>==》AspectJAroundAdvice
* <aop:before>==》AspectJMethodBeforeAdvice
* <aop:after>==》AspectJAfterAdvice
* <aop:after-returning>==》AspectJAfterReturningAdvice
* <aop:after-throwing>==》AspectJAfterThrowingAdvice
*
*/
private Class getAdviceClass(Element adviceElement, ParserContext parserContext) {
String elementName = parserContext.getDelegate().getLocalName(adviceElement);
if (BEFORE.equals(elementName)) {
return AspectJMethodBeforeAdvice.class;
}
else if (AFTER.equals(elementName)) {
return AspectJAfterAdvice.class;
}
else if (AFTER_RETURNING_ELEMENT.equals(elementName)) {
return AspectJAfterReturningAdvice.class;
}
else if (AFTER_THROWING_ELEMENT.equals(elementName)) {
return AspectJAfterThrowingAdvice.class;
}
else if (AROUND.equals(elementName)) {
return AspectJAroundAdvice.class;
}
else {
throw new IllegalArgumentException("Unknown advice kind [" + elementName + "].");
}
}
/**
* 判断是否为advice节点元素
*/
private boolean isAdviceNode(Node aNode, ParserContext parserContext) {
if (!(aNode instanceof Element)) {
return false;
}
else {
String name = parserContext.getDelegate().getLocalName(aNode);
return (BEFORE.equals(name) || AFTER.equals(name) || AFTER_RETURNING_ELEMENT.equals(name) ||
AFTER_THROWING_ELEMENT.equals(name) || AROUND.equals(name));
}
}
/**
* 解析引介增强方式 <aop:declare-parents types-matching="匹配要被引介增强的类" implement-interface="引介增强接口" default-impl="引介增强实现类"/>
* @return
*/
private AbstractBeanDefinition parseDeclareParents(Element declareParentsElement, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(DeclareParentsAdvisor.class);
//引介增强接口
builder.addConstructorArgValue(declareParentsElement.getAttribute(IMPLEMENT_INTERFACE));
//匹配要被引介增强的类
builder.addConstructorArgValue(declareParentsElement.getAttribute(TYPE_PATTERN));
//引介增强实现类全路径
String defaultImpl = declareParentsElement.getAttribute(DEFAULT_IMPL);
//引介增强实现类bean对象
String delegateRef = declareParentsElement.getAttribute(DELEGATE_REF);
if (StringUtils.hasText(defaultImpl) && !StringUtils.hasText(delegateRef)) {
builder.addConstructorArgValue(defaultImpl);
}
else if (StringUtils.hasText(delegateRef) && !StringUtils.hasText(defaultImpl)) {
builder.addConstructorArgReference(delegateRef);
}
else {
parserContext.getReaderContext().error(
"Exactly one of the " + DEFAULT_IMPL + " or " + DELEGATE_REF + " attributes must be specified",
declareParentsElement, this.parseState.snapshot());
}
AbstractBeanDefinition definition = builder.getBeanDefinition();
definition.setSource(parserContext.extractSource(declareParentsElement));
parserContext.getReaderContext().registerWithGeneratedName(definition);
return definition;
}
}
AspectJAwareAdvisorAutoProxyCreator:ConfigBeanDefinitionParser中会创建AspectJAwareAdvisorAutoProxyCreator的BeanDefinition,在ApplicationContext的refresh()中自动调用,将AspectJAwareAdvisorAutoProxyCreator转为对象。
AspectJAwareAdvisorAutoProxyCreator实现了接口BeanPostProcessor,说明它是个后置处理器,所以每个bean初始化完成后会执行BeanPostProcessor.postProcessAfterInitialization(Object bean, String beanName),对应实现在父类AbstractAutoProxyCreator
package org.springframework.aop.framework.autoproxy;
public abstract class AbstractAutoProxyCreator extends ProxyConfig
implements SmartInstantiationAwareBeanPostProcessor, BeanClassLoaderAware, BeanFactoryAware,
Ordered, AopInfrastructureBean {
// ...其它代码代码(略)
//源码分析:节点1
//关键入口
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.containsKey(cacheKey)) {
//源码分析:节点2
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
//源码分析:节点2
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.containsKey(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;
}
//源码分析:节点3
// 将当前容器中的所以Advisor和当前bean匹配,最后将匹配成功的Advisor列表返回
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//源码分析:节点4
//创建代理对象
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;
}
//源码分析:节点4
//创建代理对象
//参考优快云博文:https://blog.youkuaiyun.com/java_key_code/article/details/140076947
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
ProxyFactory proxyFactory = new ProxyFactory();
// Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.
proxyFactory.copyFrom(this);
if (!shouldProxyTargetClass(beanClass, beanName)) {
// Must allow for introductions; can't just set interfaces to
// the target's interfaces only.
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader);
for (Class<?> targetInterface : targetInterfaces) {
proxyFactory.addInterface(targetInterface);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor);
}
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(this.proxyClassLoader);
}
// ...其它代码代码(略)
}
源码分析:节点3
package org.springframework.aop.framework.autoproxy;
import java.util.List;
import org.springframework.aop.Advisor;
import org.springframework.aop.TargetSource;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.OrderComparator;
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
// ...其它代码代码(略)
//源码分析:节点3
@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource targetSource) {
//源码分析:节点3 分支1
List advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
//源码分析:节点3 分支1
protected List<Advisor> findEligibleAdvisors(Class beanClass, String beanName) {
//获取所有的候选Advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//和当前bean匹配,获取匹配成功的Advisor
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
//额外添加一个Advisor:ExposeInvocationInterceptor.ADVISOR
//将MethodInvocation放到ThreadLocal,这个类很重要
/**
public class ExposeInvocationInterceptor implements MethodInterceptor, Ordered, Serializable {
private static final ThreadLocal<MethodInvocation> invocation = new NamedThreadLocal<MethodInvocation>("Current AOP method invocation");
public Object invoke(MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = invocation.get();
invocation.set(mi);
try {
return mi.proceed();
}
finally {
invocation.set(oldInvocation);
}
}
}
*/
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
protected List<Advisor> findCandidateAdvisors() {
return this.advisorRetrievalHelper.findAdvisorBeans();
}
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
// ...其它代码代码(略)
}