直接找到解析aop标签的方法:

 protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = ; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}

由于aop属于自定义标签,所以它会执行第12行的代码。

 public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
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));
}

通过aop标签获取到它的命名空间uri,通过命名空间去找到对应的命名空间处理器,这个处理器的定义在springaop包下的一个叫spring.handlers的文件里声明了,它的内容是这样的

http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler

spring就是通过这个声明去加载这个aop命名空间处理器,通过反射的方式构建对象。构建好对象后调用它的parse方法

 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;
}

第6行的代码配置了一个org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator类,像前面的bean一样被定义成了一个BeanDefinition对象保存到了BeanFactory的beanDefinitionMap中。这个AspectJAwareAdvisorAutoProxyCreator是用来干什么的呢?看到后面才知道。

第8行获取到了这个aop:config下的子元素

是pointcut标签就处理pointcut,是advisor就处理advisor

看到第18行我们配置了一个切面,所以spring会解析这个aspect标签

 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));
List<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>();
List<BeanReference> beanReferences = new ArrayList<BeanReference>(); 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.
NodeList nodeList = aspectElement.getChildNodes();
boolean adviceFoundAlready = false;
for (int i = ; 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));
}
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) {
parsePointcut(pointcutElement, parserContext);
} parserContext.popAndRegisterContainingComponent();
}
finally {
this.parseState.pop();
}
}

第22行表示解析在aspect标签下的通知,假如此时读取到了一个before标签,开始解析这个通知

 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))); // create the method factory bean
RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class);
methodDefinition.getPropertyValues().add("targetBeanName", aspectName);
methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method"));
methodDefinition.setSynthetic(true); // create instance factory definition
RootBeanDefinition aspectFactoryDef =
new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class);
aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName);
aspectFactoryDef.setSynthetic(true); // register the pointcut
AbstractBeanDefinition adviceDef = createAdviceDefinition(
adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef,
beanDefinitions, beanReferences); // configure the advisor
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));
} // register the final advisor
parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition); return advisorDefinition;
}
finally {
this.parseState.pop();
}
}

第九行创建了一个方法工厂bean,MethodLocatingFactoryBean这个类有targetBeanName,methodName,method三个属性,method是methodName的对应Method对象。

第10行给methodDefinition设置属性targetBeanName为切面类的beanName,也就是id

第11行给methodDefinition设置属性methodName,表示这个通知要切入的方法名。

比如:

 <aop:config>
<aop:aspect id="aspect" ref="aspectID">
<aop:pointcut expression="execution(* com.test.*.*(..))"
id="cutpoint" />
<aop:before method="before" pointcut-ref="cutpoint" /> </aop:aspect> </aop:config>

那么targetBeanName为aspectID,methodName为before。

第16行创建了一个实例工厂bean,SimpleBeanFactoryAwareAspectInstanceFactory这个类除了父类的具有两个属性aspectBeanName,beanFactory,aspectBeanName指的切面的beanName,也就是上面的aspectID,beanFactory指的BeanFactory的实例

第17行给这个SimpleBeanFactoryAwareAspectInstanceFactory定义属性,aspectBeanName为aspectID

进入第21行

 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));
} ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues();
cav.addIndexedArgumentValue(METHOD_INDEX, methodDef); 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;
}

第6行创建了一个关于advice的BeanDefinition。首先它调用了getAdviceClass方法,我们进去看看

 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 + "].");
}
}

看见了吗?根据通知的类型返回相应的通知类,before对应AspectJMethodBeforeAdvice类,after对应AspectJAfterAdvice类,before和after对应的通知类的内部结构有些区别,before对应的类有before方法,但after对应的通知类是没有after方法的,代替使用的是一个invoke方法。现在不深入探讨它们是干什么的,到了调用通知方法的时候自然就明白了,这里先不管。

我们再次回到createAdviceDefinition方法

 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));
} ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues();
cav.addIndexedArgumentValue(METHOD_INDEX, methodDef); 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;
}

创建了adviceDefinition后第9第10行分别定义了通知类的一些属性,aspectName,declarationOrder

12 16 20行是判断有没有定义returning throwing arg-names属性,如果配置了,那么要给通知类加上

第25 26行要给这个通知类定义构造参数,通知类中的需要以下构造参数,比如AspectJMethodBeforeAdvice类的构造参数

AspectJMethodBeforeAdvice(
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif)

它需要一个method对象,切面表达式连接点,切面实例工厂

第25 26行给这个通知的BeanDefinition的构造加入了第一个参数的BeanDefinition==》前面已经创建好的包装MethodLocatingFactoryBean的methodDefinition。

第28行是去通知标签(如before标签)上去得pointcut或者是pointcut-ref,代码如下:

 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)) {
// Create a pointcut for the anonymous pc and register it.
String expression = element.getAttribute(POINTCUT);
AbstractBeanDefinition pointcutDefinition = createPointcutDefinition(expression);
pointcutDefinition.setSource(parserContext.extractSource(element));
return pointcutDefinition;
}
else if (element.hasAttribute(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;
}
}

第8行判断用户定义是不是pointcut属性,如果是那么就执行了以下代码

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;
}

创建了一个包装了AspectJExpressionPointcut类的BeanDefinition,并且预设声明周期为prototype,属性值EXPRESSION为用户在xml上定义的表达式

如果不是pointcut属性,是pointcut-ref属性,那么直接返回,我们又会到createAdviceDefinition方法继续往下

 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);

如果用户定义在通知标签上的属性为pointcut,那么会走第二行内的代码,如果不是,就会走第2行的代码,如果走第6行代码,那么就直接加入通知类的第二个构造参数

如果是走第6行的代码,那么就对pointcutref封装成BeanReference。成为第二个构造参数,BeanReference有个键beanName的属性,用来表示它引用了那个bean,到时候要使用的时候就是BeanFactory中拿。

第12行定义了通知类的第三个构造参数,这个构造参数是前面定义的,它是一个持有SimpleBeanFactoryAwareAspectInstanceFactory类的BeanDefinition。

此时一个持有通知类的BeanDefinition就准备好了,返回到parseAdvice中

 // register the pointcut
AbstractBeanDefinition adviceDef = createAdviceDefinition(
3 adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef,
4 beanDefinitions, beanReferences); // configure the advisor
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));
} // register the final advisor
parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition);

红色标识部分是我们返回会来的方法,继续往下看第7行,这里有创建了一个持有AspectJPointcutAdvisor类的BeanDefinition,这个AspectJPointcutAdvisor有这么一些属性

advice, pointcut,advice是一个AbstractAspectJAdvice抽象通知类型的属性,

可以看到before,after等这些通知就是继承自它。

pointcut属性是一个Pointcut类型的属性,这里肯定是用来存AspectJExpressionPointcut子类。

AspectJPointcutAdvisor类的构造器为AspectJPointcutAdvisor(AbstractAspectJAdvice advice)

所以第九行果断给构造器定义了一个刚创建好的adviceDef参数

接着就执行了下面这段代码

 public String registerWithGeneratedName(BeanDefinition beanDefinition) {
String generatedName = generateBeanName(beanDefinition);
getRegistry().registerBeanDefinition(generatedName, beanDefinition);
return generatedName;
}

传入的参数就是包装了AspectJPointcutAdvisor类的BeanDefinition,根据这个BeanDefinition生成名字形如org.springframework.aop.aspectj.AspectJPointcutAdvisor#1这样的名字,前面的类名,后面的数字表示这是创建的第几个AspectJPointcutAdvisor。这个无关紧要。

第三行将包装了AspectJPointcutAdvisor类的BeanDefinition添加到DefaultListableBeanFactory(BeanFactory子类)的beanDefinitionMap容器中

一切就绪后我们的方法返回到parseAspect方法

 AbstractBeanDefinition advisorDefinition = parseAdvice(
2 aspectName, i, aspectElement, (Element) node, parserContext, beanDefinitions, beanReferences);
3 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) {
parsePointcut(pointcutElement, parserContext);
} parserContext.popAndRegisterContainingComponent();

我们是从红色部分返回回来的。我们继续往下看第7行,它创建了一个AspectComponentDefinition对象,这个AspectComponentDefinition抛开父类,它有两个属性

private final BeanDefinition[] beanDefinitions;

private final BeanReference[] beanReferences;

它通过以下方法创建

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);
}

它把装有AspectJPointcutAdvisor类的集合和装有BeanReference的集合设置进去。new出一个AspectComponentDefinition。也就是说这个AspectComponentDefinition类包含了再其内部定义的所有通知,所有使用到的ref指定的bean引用。

回到第11行,这里是指定到aspect标签内读取pointcut标签,第13行对其进行解析

 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));
pointcutDefinition = createPointcutDefinition(expression);
pointcutDefinition.setSource(parserContext.extractSource(pointcutElement)); 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;
}

第2 3行分别获得它的id和表达式

第9行是创建一个持有AspectJExpressionPointcut class对象的BeanDefinition,这个其实在前面判断通知标签是否为pointcut属性还是pointcut-ref属性时探讨过。

第14行将创建出来的持有AspectJExpressionPointcut class对象的BeanDefinition注册到BeanFactory中的beanDefinitionMap容器中。

第20行向解析上下文中添加了一个PointcutComponentDefinition组件定义,这个切点组件定义和切面组件定义继承了同一个抽象组件类,它的自身的属性有pointcutBeanName,

pointcutDefinition,pointcutBeanName就是切点的id,pointcutDefinition就是持有AspectJExpressionPointcut 类的BeanDefinition。

到此aop命名空间处理器对aop标签的解析就结束了。

所有的BeanDefinition都已经准备就绪,接下就是实例化这些BeanDefinition了,一直返回到ClasspathxmlApplication中,调用了以下方法

// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

这个方法内部又调用了

// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();

 public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Pre-instantiating singletons in " + this);
} // Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
else {
getBean(beanName);
}
}
} // Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
smartSingleton.afterSingletonsInstantiated();
return null;
}
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}

第8行获取到所有的定义过的beanName,第11行对其进行遍历,并且进行是否是抽象的,是不是factorybean,是不是懒加载的,如果都不是直接跳到getBean()方法,getBean()方法内部又调用了

doBean方法

 protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException { final String beanName = transformedBeanName(name);
Object bean; // Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
} // Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
} if (!typeCheckOnly) {
markBeanAsCreated(beanName);
} try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
getBean(dep);
}
} // Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
} // Check if required type matches the type of the actual bean instance.
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}

第5行对beanName进行了转换,因为我们传进去的参数可能是别名。

第9行对非懒加载的bean进行实例化。

第55行对依赖进行判断,如果有依赖还要进行循环依赖判断,构造器循环依赖是无法解决的会直接抛出异常,setter方法依赖就不会。

 // Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

第3行

 public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<Exception>();
}
try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}

第四行先冲到BeanFactory的singletonObjects容器中查看这个类是否已经被创建了。

第21行调用了一下代码

new ObjectFactory<Object>() {
    @Override
    public Object getObject() throws BeansException {
       try {
          return createBean(beanName, mbd, args);
}

继续跟踪createBean方法,假设当前要创建的对象是AspectJAwareAdvisorAutoProxyCreator类的实例

那么beanName表示对应这个BeanDefinition的id名,mbd就是包装了AspectJAwareAdvisorAutoProxyCreator的BeanDefinition。

 protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd; // Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
} // Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
} try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
} Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}

第10行获取这个BeanDefinition内持有的class对象,所以这里是AspectJAwareAdvisorAutoProxyCreator类的class对象

第18行是准备方法覆盖,这个一般在使用了lookup-method,replace-method的时候使用。这里明显为空

第27行检查是否实现了InstantiationAwareBeanPostProcessor接口,如果是,这里会调用实现的postProcessBeforeInstantiation方法。

第37行方法中调用了instanceWrapper = createBeanInstance(beanName, mbd, args);方法

 protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
// Make sure bean class is actually resolved at this point.
Class<?> beanClass = resolveBeanClass(mbd, beanName); if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
} if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
} // Shortcut when re-creating the same bean...
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
return instantiateBean(beanName, mbd);
}
} // Need to determine the constructor...
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
} // No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
}

第5行判断这个bean是不是public的,有没有访问权限,没有就抛异常

第10行是判断它是否有工厂方法,如果有工厂方法,就用工厂方法创建对象。

第35确定其是否需要构造器注入,如果是的话,那么会执行第39行,构造器注入的方式,否则直接到第43行,用无参构造器处理

进入这个instantiateBean方法

 protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
return getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
}, getAccessControlContext());
}
else {
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}

第14行getInstantiationStrategy()获取实例化策略,有SimpleInstantiationStrategy,CglibSubclassingInstantiationStrategy策略

这里我们假设是CglibSubclassingInstantiationStrategy策略,接下来调用了这个策略的instantiate方法,我们这里使用的CglibSubclassingInstantiationStrategy策略。进去看看吧

 public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
if (bd.getMethodOverrides().isEmpty()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class<?> clazz = bd.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
@Override
public Constructor<?> run() throws Exception {
return clazz.getDeclaredConstructor((Class[]) null);
}
});
}
else {
constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}

第9行判断这个类是不是接口,如果是接口,那就要报错,不能实例化

第22行获取到这个class的无参构造器

第31行代码

 public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
Assert.notNull(ctor, "Constructor must not be null");
try {
ReflectionUtils.makeAccessible(ctor);
return ctor.newInstance(args);
}
catch (InstantiationException ex) {
throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
}
catch (IllegalAccessException ex) {
throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);
}
catch (IllegalArgumentException ex) {
throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);
}
catch (InvocationTargetException ex) {
throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());
}
}

第4行判断这个构造方法是否可见,不可见就设置为可见,然后使用构造器构造对象

就这样,对象就被创建了。创建了这个类的实例后还有注入相应的非依赖属性,比如一些原始类型的属性

spring使用了JDK自带的PropertyDescriptor类,通过获取writeMethod将值设置进去。

这个方法在BeanWrapperImpl类中定义,部分代码

public void setValue(final Object object, Object valueToApply) throws Exception {
       final Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
       ((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
       this.pd.getWriteMethod());

获取到了它对应属性的set方法。

调用writeMethod.invoke(getWrappedInstance(), value);将值设置进去

这个类在设置好值之后,会判断是否需要进行初始化,由于这个类实现了InstantiationAwareBeanPostProcessor接口,所以最后还会调用

postProcessAfterInitialization方法

最后将创建好的bean放到singletonObjects中

之前创建了AspectJAwareAdvisorAutoProxyCreator的实例,它实现了BeanPostProcessor接口,所以在BeanFactory中的beanPostProcessors集合中会保存它。

也就是说在后续创建其他的bean的过程中都或调用AspectJAwareAdvisorAutoProxyCreator的postProcessBeforeInitialization和postProcessAfterInitialization(Object, String)方法

 public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName); if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
} // Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
if (beanName != null) {
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
this.targetSourcedBeans.add(beanName);
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
} return null;
}

重点看到第8行shouldSkip方法

 protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// TODO: Consider optimization by caching the list of the aspect names
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor) {
if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
return true;
}
}
}
return super.shouldSkip(beanClass, beanName);
}

第三行表示去获取候选的通知器。调用了advisors.add(this.beanFactory.getBean(name, Advisor.class));方法

其中的getBean方法很眼熟,跟上面创建bean的操作一样,获取到了所有的advisor。

将获取到advisor遍历,取出当前advisor中的advice拿到它对应的aspectName和当前要创建的bean的beanName进行equals,如果相等,那就返回TRUE,并将使用当前beanClass生成的CacheKey保存到AspectJAwareAdvisorAutoProxyCreator父类的一个叫做advisedBeans的map集合中,为什么这么做呢?因为用户定义的切面可能有多个。不符合的bean就跳过(也就是遇到不是aspect的bean跳过)

一切准备就绪,开始创建代理对象

调用了AspectJAwareAdvisorAutoProxyCreator的

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
   if (bean != null) {
      Object cacheKey = getCacheKey(bean.getClass(), beanName);
       if (!this.earlyProxyReferences.contains(cacheKey)) {
      return wrapIfNecessary(bean, beanName, cacheKey);
    }
   }
   return bean;
}

我们进到wrapIfNecessary看看

 // Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}

进入第2行代码

 protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}

第2行代码通过当前类和类名寻找匹配的通知器

findEligibleAdvisors:
 protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}

第二行获取到了所有候选的通知器

第三行获取到匹配当前bean的通知器

内部调用了AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);这个方法

内部又调用了canApply(pca.getPointcut(), targetClass, hasIntroductions);方法

 for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}

通过反射拿到当前类的所有方法,使用一个方法匹配器去配置当前方法是否可以匹配切点

如果匹配将对应的通知器保存起来,最后返回回到下面一段代码

Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

最后我们看到createAopProxy犯法,这个方法的代码
 public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}

第8行判断它是否实现了接口,如果实现了接口,那么就使用JDK的动态代理

否则使用第11行的cglib代理

接下类调用了getProxy方法,里面是我们属性代理创建过程,这里拿cglib为例

 // Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader)); Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = ; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types); // Generate the proxy class and create a proxy instance.
return createProxyClassAndInstance(enhancer, callbacks);

看到第26行

createProxyClassAndInstance这个方法有这么一行代码

Class<?> proxyClass = enhancer.createClass();

这行代码用debug跟进去之后,发现最后它创建了实现了MethodInterceptor的方法拦截器,比如像下面这个

public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
   this.advice = advice;
}

所有的通知最后都会被封装成一个MethodInterceptor。

 public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>();
Advice advice = advisor.getAdvice();
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
}

将所有的通知都打包成interceptor之后变成数组返回

MethodInterceptor接口只有一个方法Object invoke(MethodInvocation invocation) throws Throwable;

拿其中一个MethodBeforeAdviceInterceptor方法分析一下他的invoke方法

 public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
return mi.proceed();
}

第2行表示在执行目标方法前执行了这个通知类方法

当给每一个方法确定了匹配的通知拦截器后,准备工作也就完成了。

当我们去BeanFactory获取对象的时候,比如我们获取的是一个叫做UserService的类,这个service被应用了aop,所以很显然我们获取到的是一个代理类

我们用这个代理类去调用一个被增强的方法

加入代码是这样写的UserService service = beanFactory.getBean(UserService.class);

service.save();

从这里开始

当调用了这个方法后我们进入了一个DynamicAdvisedInterceptor类的intercept方法

     public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Class<?> targetClass = null;
Object target = null;
try {
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// May be null. Get as late as possible to minimize the time we
// "own" the target, in case it comes from a pool...
target = getTarget();
if (target != null) {
targetClass = target.getClass();
}
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// We can skip creating a MethodInvocation: just invoke the target directly.
// Note that the final invoker must be an InvokerInterceptor, so we know
// it does nothing but a reflective operation on the target, and no hot
// swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// We need to create a method invocation...
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null) {
releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}

第14行获取目标代理类

第18行获取符合代理目标的拦截器链。也就是一个集合装了一堆符合条件的拦截器,比如前置通知拦截器,后置通知拦截器

第32行创建一个CglibMethodInvocation的实例,并且调用它的proceed方法

 public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - ) {
return invokeJoinpoint();
} Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}

第3行代码查看当前下标和当前拦截器链的个数减一是否相等了,如果相等了,那么就调用被代理的目标方法,

这里使用了一个currentInterceptorIndex来表示当前已经调用到了哪个拦截器
第8行获取当前下标的拦截器 ,并且调用它的invoke方法,把自身也传进去
假设当前的拦截器是AspectJAfterAdvice拦截器,那么它的invoke方法如下
 public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}

在mi.proceed()结束后才调用通知方法,所以可以想象,before通知的只要把调用通知的方法写在mi.proceed()前面,after通知把通知方法写在后面,那不就做到在原始方法前面条用逻辑和后面调用逻辑了吗?而且你不觉得这种调用方式很想责任链模式吗?那throwing通知是怎么做的呢?throwing通知当然是使用try catch将mi.process()包裹,然后在catch中写逻辑。那returning

呢?returning就在mi.process()返回值后写逻辑。

这时候我们想啊。事物是怎么配置的呢?事物也一样都是使用的aop,它只不过在调用mi.process()方法的前面去DataSource中获取到了一个连接,将这个连接像jdbc一样操作,设置它不自动提交,设置隔离机制等等把获取到的线程保存到本地线程中(ThreadLocal中),然后在mi.process()方法上使用了try catch,一旦发生异常,并且默认异常为runtimeException或者Error,那么就会滚。这里提到了将连接保存到本地线程中,所以在使用hibernate的时候我们应当使用getCurrentSession(),而不是openSession。

总结:spring aop的原理就是使用动态代理产生一个代理对象,然后通过代理对象去调用了一个methodInvocation,这个methodInvocation持有通知的拦截器链的集合,还有一个表示当前调用到了哪一个拦截器的下标。还有目标方法,和目标对象,目标方法的参数。就像web中的过滤器一样运行(实际上过滤器链也是这个原理)。

spring aop(四)的更多相关文章

  1. Spring AOP四种实现方式Demo详解与相关知识探究

    一.前言 在网络上看到一篇博客Spring实现AOP的4种方式,博主写的很通俗易懂,但排版实在抓狂,对于我这么一个对排版.代码格式有强迫症的人来说,实在是不能忍受~~~~(>_<)~~~~ ...

  2. Spring AOP小记

    一.概述 在通常的开发过程中,我们调用的顺序通常是controller->service-dao,其中,service中包含着太多的业务逻辑,并且还要不断调用dao来实现自身的业务逻辑,经常会导 ...

  3. Spring AOP实现方式四之注入式AspectJ切面【附源码】

    现在我们要讲的是第四种AOP实现之注入式AspectJ切面 通过简单的配置就可以实现AOP了. 源码结构: 1.首先我们新建一个接口,love 谈恋爱接口. package com.spring.ao ...

  4. Spring(二十):Spring AOP(四):基于配置文件的方式来配置 AOP

    基于配置文件的方式来配置 AOP 前边三个章节<Spring(十七):Spring AOP(一):简介>.<Spring(十八):Spring AOP(二):通知(前置.后置.返回. ...

  5. Spring系列(四):Spring AOP详解和实现方式(xml配置和注解配置)

    参考文章:http://www.cnblogs.com/hongwz/p/5764917.html 一.什么是AOP AOP(Aspect Oriented Programming),即面向切面编程, ...

  6. Spring系列(四):Spring AOP详解

    一.AOP是什么 AOP(面向切面编程),可以说是一种编程思想,其中的Spring AOP和AspectJ都是现实了这种编程思想.相对OOP(面向过程编程)来说,提供了另外一种编程方式,对于OOP过程 ...

  7. 【Spring AOP】切入点表达式(四)

    一.切入点指示符 切入点指示符用来指示切入点表达式目的,在Spring AOP中目前只有执行方法这一个连接点,Spring AOP支持的AspectJ切入点指示符如下: execution:用于匹配方 ...

  8. spring深入学习(四)-----spring aop

    AOP概述 aop其实就是面向切面编程,举个例子,比如项目中有n个方法是对外提供http服务的,那么如果我需要对这些http服务进行响应时间的监控,按照传统的方式就是每个方法中添加相应的逻辑,但是这些 ...

  9. Spring学习十四----------Spring AOP实例

    © 版权声明:本文为博主原创文章,转载请注明出处 实例 1.项目结构 2.pom.xml <project xmlns="http://maven.apache.org/POM/4.0 ...

  10. spring AOP详解四

    AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于处理一些具有横切性质的系统级服务,如事务管理.安全检查.缓存.对象池管理等.AOP 实现的关键就在于 ...

随机推荐

  1. Node 在chrome上调试

    先确保node是否安装成功: 然后 1.创建node_module块,并在同一层级创建一个服务: 如server.js: 2.下载调试工具devtool: npm install -g devtool ...

  2. mysql数据库之表关系

    外键 前戏之一对多关系 # 定义一张部门员工表id name gender dep_name dep_desc1 jason male 教学部 教书育人2 egon male 外交部 漂泊游荡3 ta ...

  3. spring 5.x 系列第12篇 —— 整合memcached (代码配置方式)

    文章目录 一.说明 1.1 XMemcached客户端说明 1.2 项目结构说明 1.3 依赖说明 二.spring 整合 memcached 2.1 单机配置 2.2 集群配置 2.3 存储基本类型 ...

  4. 本地线程-ThreadLocal

    线程本地存储是一个自动化机制,可以为使用相同变量的每个不同的线程都创建不同的存储.简单来说,就是对于某个变量,针对不同的线程存储不同的值. 实例: import java.util.Random; i ...

  5. Java进阶——高性能MySQL(一)

    MySQL逻辑架构: 链接管理与安全性: MySQL5.5或更高版本版本提供了一个API,支持线程池(Thread-Pooling)插件,可以使用池中的少量线程来服务大量的连接. 优化与并行: MyS ...

  6. PATA 1036. Boys vs Girls (25)

    https://www.patest.cn/contests/pat-a-practise/1036 #include <bits/stdc++.h> using namespace st ...

  7. Matplotlib快速入门

    Matplotlib 可能还有小伙伴不知道Matplotlib是什么,下面是维基百科的介绍. Matplotlib 是Python编程语言的一个绘图库及其数值数学扩展 NumPy.它为利用通用的图形用 ...

  8. scrapy实战7爬取搜狗微信:

    爬取微信热门文章标题,内容,内容地址,微信公众号,公众号地址,发布日期等 如图 源码地址:https://github.com/huwei86/sougouweixin

  9. Maven打包成Jar文件时依赖包的问题

    我们项目中使用到第三方的库文件,这些jar库文件并没有放到Maven中央库上,导致我们需要在项目中自己配置使用.我们的两三个开发人员对Java都是很熟,因此在使用中遇到了一些问题,表现在:在本地中引入 ...

  10. 关于pcl索引的使用

    最近开始动手做实验,之前写了一个小实验利用到了PCL库中的索引: 现在在写利用PCL中的RegionGrowing类来分割生成面片,无论是迭代生成还是进行提取都需要用到pcl库中定义的索引, 虽然搞的 ...