首页 > 代码库 > spring aop(四)
spring aop(四)
直接找到解析aop标签的方法:
1 protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { 2 if (delegate.isDefaultNamespace(root)) { 3 NodeList nl = root.getChildNodes(); 4 for (int i = 0; i < nl.getLength(); i++) { 5 Node node = nl.item(i); 6 if (node instanceof Element) { 7 Element ele = (Element) node; 8 if (delegate.isDefaultNamespace(ele)) { 9 parseDefaultElement(ele, delegate); 10 } 11 else { 12 delegate.parseCustomElement(ele); 13 } 14 } 15 } 16 } 17 else { 18 delegate.parseCustomElement(root); 19 } 20 }
由于aop属于自定义标签,所以它会执行第12行的代码。
1 public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) { 2 String namespaceUri = getNamespaceURI(ele); 3 NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); 4 if (handler == null) { 5 error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); 6 return null; 7 } 8 return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); 9 }
通过aop标签获取到它的命名空间uri,通过命名空间去找到对应的命名空间处理器,这个处理器的定义在springaop包下的一个叫spring.handlers的文件里声明了,它的内容是这样的
http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler
spring就是通过这个声明去加载这个aop命名空间处理器,通过反射的方式构建对象。构建好对象后调用它的parse方法
1 public BeanDefinition parse(Element element, ParserContext parserContext) { 2 CompositeComponentDefinition compositeDef = 3 new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element)); 4 parserContext.pushContainingComponent(compositeDef); 5 6 configureAutoProxyCreator(parserContext, element); 7 8 List<Element> childElts = DomUtils.getChildElements(element); 9 for (Element elt: childElts) { 10 String localName = parserContext.getDelegate().getLocalName(elt); 11 if (POINTCUT.equals(localName)) { 12 parsePointcut(elt, parserContext); 13 } 14 else if (ADVISOR.equals(localName)) { 15 parseAdvisor(elt, parserContext); 16 } 17 else if (ASPECT.equals(localName)) { 18 parseAspect(elt, parserContext); 19 } 20 } 21 22 parserContext.popAndRegisterContainingComponent(); 23 return null; 24 }
第6行的代码配置了一个org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator类,像前面的bean一样被定义成了一个BeanDefinition对象保存到了BeanFactory的beanDefinitionMap中。这个AspectJAwareAdvisorAutoProxyCreator是用来干什么的呢?看到后面才知道。
第8行获取到了这个aop:config下的子元素
是pointcut标签就处理pointcut,是advisor就处理advisor
看到第18行我们配置了一个切面,所以spring会解析这个aspect标签
1 private void parseAspect(Element aspectElement, ParserContext parserContext) { 2 String aspectId = aspectElement.getAttribute(ID); 3 String aspectName = aspectElement.getAttribute(REF); 4 5 try { 6 this.parseState.push(new AspectEntry(aspectId, aspectName)); 7 List<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>(); 8 List<BeanReference> beanReferences = new ArrayList<BeanReference>(); 9 10 List<Element> declareParents = DomUtils.getChildElementsByTagName(aspectElement, DECLARE_PARENTS); 11 for (int i = METHOD_INDEX; i < declareParents.size(); i++) { 12 Element declareParentsElement = declareParents.get(i); 13 beanDefinitions.add(parseDeclareParents(declareParentsElement, parserContext)); 14 } 15 16 // We have to parse "advice" and all the advice kinds in one loop, to get the 17 // ordering semantics right. 18 NodeList nodeList = aspectElement.getChildNodes(); 19 boolean adviceFoundAlready = false; 20 for (int i = 0; i < nodeList.getLength(); i++) { 21 Node node = nodeList.item(i); 22 if (isAdviceNode(node, parserContext)) { 23 if (!adviceFoundAlready) { 24 adviceFoundAlready = true; 25 if (!StringUtils.hasText(aspectName)) { 26 parserContext.getReaderContext().error( 27 "<aspect> tag needs aspect bean reference via ‘ref‘ attribute when declaring advices.", 28 aspectElement, this.parseState.snapshot()); 29 return; 30 } 31 beanReferences.add(new RuntimeBeanReference(aspectName)); 32 } 33 AbstractBeanDefinition advisorDefinition = parseAdvice( 34 aspectName, i, aspectElement, (Element) node, parserContext, beanDefinitions, beanReferences); 35 beanDefinitions.add(advisorDefinition); 36 } 37 } 38 39 AspectComponentDefinition aspectComponentDefinition = createAspectComponentDefinition( 40 aspectElement, aspectId, beanDefinitions, beanReferences, parserContext); 41 parserContext.pushContainingComponent(aspectComponentDefinition); 42 43 List<Element> pointcuts = DomUtils.getChildElementsByTagName(aspectElement, POINTCUT); 44 for (Element pointcutElement : pointcuts) { 45 parsePointcut(pointcutElement, parserContext); 46 } 47 48 parserContext.popAndRegisterContainingComponent(); 49 } 50 finally { 51 this.parseState.pop(); 52 } 53 }
第22行表示解析在aspect标签下的通知,假如此时读取到了一个before标签,开始解析这个通知
1 private AbstractBeanDefinition parseAdvice( 2 String aspectName, int order, Element aspectElement, Element adviceElement, ParserContext parserContext, 3 List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) { 4 5 try { 6 this.parseState.push(new AdviceEntry(parserContext.getDelegate().getLocalName(adviceElement))); 7 8 // create the method factory bean 9 RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class); 10 methodDefinition.getPropertyValues().add("targetBeanName", aspectName); 11 methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method")); 12 methodDefinition.setSynthetic(true); 13 14 // create instance factory definition 15 RootBeanDefinition aspectFactoryDef = 16 new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class); 17 aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName); 18 aspectFactoryDef.setSynthetic(true); 19 20 // register the pointcut 21 AbstractBeanDefinition adviceDef = createAdviceDefinition( 22 adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef, 23 beanDefinitions, beanReferences); 24 25 // configure the advisor 26 RootBeanDefinition advisorDefinition = new RootBeanDefinition(AspectJPointcutAdvisor.class); 27 advisorDefinition.setSource(parserContext.extractSource(adviceElement)); 28 advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef); 29 if (aspectElement.hasAttribute(ORDER_PROPERTY)) { 30 advisorDefinition.getPropertyValues().add( 31 ORDER_PROPERTY, aspectElement.getAttribute(ORDER_PROPERTY)); 32 } 33 34 // register the final advisor 35 parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition); 36 37 return advisorDefinition; 38 } 39 finally { 40 this.parseState.pop(); 41 } 42 }
第九行创建了一个方法工厂bean,MethodLocatingFactoryBean这个类有targetBeanName,methodName,method三个属性,method是methodName的对应Method对象。
第10行给methodDefinition设置属性targetBeanName为切面类的beanName,也就是id
第11行给methodDefinition设置属性methodName,表示这个通知要切入的方法名。
比如:
1 <aop:config> 2 <aop:aspect id="aspect" ref="aspectID"> 3 <aop:pointcut expression="execution(* com.test.*.*(..))" 4 id="cutpoint" /> 5 <aop:before method="before" pointcut-ref="cutpoint" /> 6 7 </aop:aspect> 8 9 </aop:config>
那么targetBeanName为aspectID,methodName为before。
第16行创建了一个实例工厂bean,SimpleBeanFactoryAwareAspectInstanceFactory这个类除了父类的具有两个属性aspectBeanName,beanFactory,aspectBeanName指的切面的beanName,也就是上面的aspectID,beanFactory指的BeanFactory的实例
第17行给这个SimpleBeanFactoryAwareAspectInstanceFactory定义属性,aspectBeanName为aspectID
进入第21行
1 private AbstractBeanDefinition createAdviceDefinition( 2 Element adviceElement, ParserContext parserContext, String aspectName, int order, 3 RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef, 4 List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) { 5 6 RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement, parserContext)); 7 adviceDefinition.setSource(parserContext.extractSource(adviceElement)); 8 9 adviceDefinition.getPropertyValues().add(ASPECT_NAME_PROPERTY, aspectName); 10 adviceDefinition.getPropertyValues().add(DECLARATION_ORDER_PROPERTY, order); 11 12 if (adviceElement.hasAttribute(RETURNING)) { 13 adviceDefinition.getPropertyValues().add( 14 RETURNING_PROPERTY, adviceElement.getAttribute(RETURNING)); 15 } 16 if (adviceElement.hasAttribute(THROWING)) { 17 adviceDefinition.getPropertyValues().add( 18 THROWING_PROPERTY, adviceElement.getAttribute(THROWING)); 19 } 20 if (adviceElement.hasAttribute(ARG_NAMES)) { 21 adviceDefinition.getPropertyValues().add( 22 ARG_NAMES_PROPERTY, adviceElement.getAttribute(ARG_NAMES)); 23 } 24 25 ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues(); 26 cav.addIndexedArgumentValue(METHOD_INDEX, methodDef); 27 28 Object pointcut = parsePointcutProperty(adviceElement, parserContext); 29 if (pointcut instanceof BeanDefinition) { 30 cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcut); 31 beanDefinitions.add((BeanDefinition) pointcut); 32 } 33 else if (pointcut instanceof String) { 34 RuntimeBeanReference pointcutRef = new RuntimeBeanReference((String) pointcut); 35 cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcutRef); 36 beanReferences.add(pointcutRef); 37 } 38 39 cav.addIndexedArgumentValue(ASPECT_INSTANCE_FACTORY_INDEX, aspectFactoryDef); 40 41 return adviceDefinition; 42 }
第6行创建了一个关于advice的BeanDefinition。首先它调用了getAdviceClass方法,我们进去看看
1 private Class<?> getAdviceClass(Element adviceElement, ParserContext parserContext) { 2 String elementName = parserContext.getDelegate().getLocalName(adviceElement); 3 if (BEFORE.equals(elementName)) { 4 return AspectJMethodBeforeAdvice.class; 5 } 6 else if (AFTER.equals(elementName)) { 7 return AspectJAfterAdvice.class; 8 } 9 else if (AFTER_RETURNING_ELEMENT.equals(elementName)) { 10 return AspectJAfterReturningAdvice.class; 11 } 12 else if (AFTER_THROWING_ELEMENT.equals(elementName)) { 13 return AspectJAfterThrowingAdvice.class; 14 } 15 else if (AROUND.equals(elementName)) { 16 return AspectJAroundAdvice.class; 17 } 18 else { 19 throw new IllegalArgumentException("Unknown advice kind [" + elementName + "]."); 20 } 21 }
看见了吗?根据通知的类型返回相应的通知类,before对应AspectJMethodBeforeAdvice类,after对应AspectJAfterAdvice类,before和after对应的通知类的内部结构有些区别,before对应的类有before方法,但after对应的通知类是没有after方法的,代替使用的是一个invoke方法。现在不深入探讨它们是干什么的,到了调用通知方法的时候自然就明白了,这里先不管。
我们再次回到createAdviceDefinition方法
1 private AbstractBeanDefinition createAdviceDefinition( 2 Element adviceElement, ParserContext parserContext, String aspectName, int order, 3 RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef, 4 List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) { 5 6 RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement, parserContext)); 7 adviceDefinition.setSource(parserContext.extractSource(adviceElement)); 8 9 adviceDefinition.getPropertyValues().add(ASPECT_NAME_PROPERTY, aspectName); 10 adviceDefinition.getPropertyValues().add(DECLARATION_ORDER_PROPERTY, order); 11 12 if (adviceElement.hasAttribute(RETURNING)) { 13 adviceDefinition.getPropertyValues().add( 14 RETURNING_PROPERTY, adviceElement.getAttribute(RETURNING)); 15 } 16 if (adviceElement.hasAttribute(THROWING)) { 17 adviceDefinition.getPropertyValues().add( 18 THROWING_PROPERTY, adviceElement.getAttribute(THROWING)); 19 } 20 if (adviceElement.hasAttribute(ARG_NAMES)) { 21 adviceDefinition.getPropertyValues().add( 22 ARG_NAMES_PROPERTY, adviceElement.getAttribute(ARG_NAMES)); 23 } 24 25 ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues(); 26 cav.addIndexedArgumentValue(METHOD_INDEX, methodDef); 27 28 Object pointcut = parsePointcutProperty(adviceElement, parserContext); 29 if (pointcut instanceof BeanDefinition) { 30 cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcut); 31 beanDefinitions.add((BeanDefinition) pointcut); 32 } 33 else if (pointcut instanceof String) { 34 RuntimeBeanReference pointcutRef = new RuntimeBeanReference((String) pointcut); 35 cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcutRef); 36 beanReferences.add(pointcutRef); 37 } 38 39 cav.addIndexedArgumentValue(ASPECT_INSTANCE_FACTORY_INDEX, aspectFactoryDef); 40 41 return adviceDefinition; 42 }
创建了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,代码如下:
1 private Object parsePointcutProperty(Element element, ParserContext parserContext) { 2 if (element.hasAttribute(POINTCUT) && element.hasAttribute(POINTCUT_REF)) { 3 parserContext.getReaderContext().error( 4 "Cannot define both ‘pointcut‘ and ‘pointcut-ref‘ on <advisor> tag.", 5 element, this.parseState.snapshot()); 6 return null; 7 } 8 else if (element.hasAttribute(POINTCUT)) { 9 // Create a pointcut for the anonymous pc and register it. 10 String expression = element.getAttribute(POINTCUT); 11 AbstractBeanDefinition pointcutDefinition = createPointcutDefinition(expression); 12 pointcutDefinition.setSource(parserContext.extractSource(element)); 13 return pointcutDefinition; 14 } 15 else if (element.hasAttribute(POINTCUT_REF)) { 16 String pointcutRef = element.getAttribute(POINTCUT_REF); 17 if (!StringUtils.hasText(pointcutRef)) { 18 parserContext.getReaderContext().error( 19 "‘pointcut-ref‘ attribute contains empty value.", element, this.parseState.snapshot()); 20 return null; 21 } 22 return pointcutRef; 23 } 24 else { 25 parserContext.getReaderContext().error( 26 "Must define one of ‘pointcut‘ or ‘pointcut-ref‘ on <advisor> tag.", 27 element, this.parseState.snapshot()); 28 return null; 29 } 30 }
第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方法继续往下
1 Object pointcut = parsePointcutProperty(adviceElement, parserContext); 2 if (pointcut instanceof BeanDefinition) { 3 cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcut); 4 beanDefinitions.add((BeanDefinition) pointcut); 5 } 6 else if (pointcut instanceof String) { 7 RuntimeBeanReference pointcutRef = new RuntimeBeanReference((String) pointcut); 8 cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcutRef); 9 beanReferences.add(pointcutRef); 10 } 11 12 cav.addIndexedArgumentValue(ASPECT_INSTANCE_FACTORY_INDEX, aspectFactoryDef);
如果用户定义在通知标签上的属性为pointcut,那么会走第二行内的代码,如果不是,就会走第2行的代码,如果走第6行代码,那么就直接加入通知类的第二个构造参数
如果是走第6行的代码,那么就对pointcutref封装成BeanReference。成为第二个构造参数,BeanReference有个键beanName的属性,用来表示它引用了那个bean,到时候要使用的时候就是BeanFactory中拿。
第12行定义了通知类的第三个构造参数,这个构造参数是前面定义的,它是一个持有SimpleBeanFactoryAwareAspectInstanceFactory类的BeanDefinition。
此时一个持有通知类的BeanDefinition就准备好了,返回到parseAdvice中
1 // register the pointcut 2 AbstractBeanDefinition adviceDef = createAdviceDefinition( 3 adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef, 4 beanDefinitions, beanReferences); 5 6 // configure the advisor 7 RootBeanDefinition advisorDefinition = new RootBeanDefinition(AspectJPointcutAdvisor.class); 8 advisorDefinition.setSource(parserContext.extractSource(adviceElement)); 9 advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef); 10 if (aspectElement.hasAttribute(ORDER_PROPERTY)) { 11 advisorDefinition.getPropertyValues().add( 12 ORDER_PROPERTY, aspectElement.getAttribute(ORDER_PROPERTY)); 13 } 14 15 // register the final advisor 16 parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition);
红色标识部分是我们返回会来的方法,继续往下看第7行,这里有创建了一个持有AspectJPointcutAdvisor类的BeanDefinition,这个AspectJPointcutAdvisor有这么一些属性
advice, pointcut,advice是一个AbstractAspectJAdvice抽象通知类型的属性,
可以看到before,after等这些通知就是继承自它。
pointcut属性是一个Pointcut类型的属性,这里肯定是用来存AspectJExpressionPointcut子类。
AspectJPointcutAdvisor类的构造器为AspectJPointcutAdvisor(AbstractAspectJAdvice advice)
所以第九行果断给构造器定义了一个刚创建好的adviceDef参数
接着就执行了下面这段代码
1 public String registerWithGeneratedName(BeanDefinition beanDefinition) { 2 String generatedName = generateBeanName(beanDefinition); 3 getRegistry().registerBeanDefinition(generatedName, beanDefinition); 4 return generatedName; 5 }
传入的参数就是包装了AspectJPointcutAdvisor类的BeanDefinition,根据这个BeanDefinition生成名字形如org.springframework.aop.aspectj.AspectJPointcutAdvisor#1这样的名字,前面的类名,后面的数字表示这是创建的第几个AspectJPointcutAdvisor。这个无关紧要。
第三行将包装了AspectJPointcutAdvisor类的BeanDefinition添加到DefaultListableBeanFactory(BeanFactory子类)的beanDefinitionMap容器中
一切就绪后我们的方法返回到parseAspect方法
1 AbstractBeanDefinition advisorDefinition = parseAdvice( 2 aspectName, i, aspectElement, (Element) node, parserContext, beanDefinitions, beanReferences); 3 beanDefinitions.add(advisorDefinition); 4 } 5 } 6 7 AspectComponentDefinition aspectComponentDefinition = createAspectComponentDefinition( 8 aspectElement, aspectId, beanDefinitions, beanReferences, parserContext); 9 parserContext.pushContainingComponent(aspectComponentDefinition); 10 11 List<Element> pointcuts = DomUtils.getChildElementsByTagName(aspectElement, POINTCUT); 12 for (Element pointcutElement : pointcuts) { 13 parsePointcut(pointcutElement, parserContext); 14 } 15 16 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行对其进行解析
1 private AbstractBeanDefinition parsePointcut(Element pointcutElement, ParserContext parserContext) { 2 String id = pointcutElement.getAttribute(ID); 3 String expression = pointcutElement.getAttribute(EXPRESSION); 4 5 AbstractBeanDefinition pointcutDefinition = null; 6 7 try { 8 this.parseState.push(new PointcutEntry(id)); 9 pointcutDefinition = createPointcutDefinition(expression); 10 pointcutDefinition.setSource(parserContext.extractSource(pointcutElement)); 11 12 String pointcutBeanName = id; 13 if (StringUtils.hasText(pointcutBeanName)) { 14 parserContext.getRegistry().registerBeanDefinition(pointcutBeanName, pointcutDefinition); 15 } 16 else { 17 pointcutBeanName = parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition); 18 } 19 20 parserContext.registerComponent( 21 new PointcutComponentDefinition(pointcutBeanName, pointcutDefinition, expression)); 22 } 23 finally { 24 this.parseState.pop(); 25 } 26 27 return pointcutDefinition; 28 }
第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();
1 public void preInstantiateSingletons() throws BeansException { 2 if (this.logger.isDebugEnabled()) { 3 this.logger.debug("Pre-instantiating singletons in " + this); 4 } 5 6 // Iterate over a copy to allow for init methods which in turn register new bean definitions. 7 // While this may not be part of the regular factory bootstrap, it does otherwise work fine. 8 List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames); 9 10 // Trigger initialization of all non-lazy singleton beans... 11 for (String beanName : beanNames) { 12 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); 13 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { 14 if (isFactoryBean(beanName)) { 15 final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName); 16 boolean isEagerInit; 17 if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { 18 isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() { 19 @Override 20 public Boolean run() { 21 return ((SmartFactoryBean<?>) factory).isEagerInit(); 22 } 23 }, getAccessControlContext()); 24 } 25 else { 26 isEagerInit = (factory instanceof SmartFactoryBean && 27 ((SmartFactoryBean<?>) factory).isEagerInit()); 28 } 29 if (isEagerInit) { 30 getBean(beanName); 31 } 32 } 33 else { 34 getBean(beanName); 35 } 36 } 37 } 38 39 // Trigger post-initialization callback for all applicable beans... 40 for (String beanName : beanNames) { 41 Object singletonInstance = getSingleton(beanName); 42 if (singletonInstance instanceof SmartInitializingSingleton) { 43 final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; 44 if (System.getSecurityManager() != null) { 45 AccessController.doPrivileged(new PrivilegedAction<Object>() { 46 @Override 47 public Object run() { 48 smartSingleton.afterSingletonsInstantiated(); 49 return null; 50 } 51 }, getAccessControlContext()); 52 } 53 else { 54 smartSingleton.afterSingletonsInstantiated(); 55 } 56 } 57 } 58 }
第8行获取到所有的定义过的beanName,第11行对其进行遍历,并且进行是否是抽象的,是不是factorybean,是不是懒加载的,如果都不是直接跳到getBean()方法,getBean()方法内部又调用了
doBean方法
1 protected <T> T doGetBean( 2 final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) 3 throws BeansException { 4 5 final String beanName = transformedBeanName(name); 6 Object bean; 7 8 // Eagerly check singleton cache for manually registered singletons. 9 Object sharedInstance = getSingleton(beanName); 10 if (sharedInstance != null && args == null) { 11 if (logger.isDebugEnabled()) { 12 if (isSingletonCurrentlyInCreation(beanName)) { 13 logger.debug("Returning eagerly cached instance of singleton bean ‘" + beanName + 14 "‘ that is not fully initialized yet - a consequence of a circular reference"); 15 } 16 else { 17 logger.debug("Returning cached instance of singleton bean ‘" + beanName + "‘"); 18 } 19 } 20 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); 21 } 22 23 else { 24 // Fail if we‘re already creating this bean instance: 25 // We‘re assumably within a circular reference. 26 if (isPrototypeCurrentlyInCreation(beanName)) { 27 throw new BeanCurrentlyInCreationException(beanName); 28 } 29 30 // Check if bean definition exists in this factory. 31 BeanFactory parentBeanFactory = getParentBeanFactory(); 32 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { 33 // Not found -> check parent. 34 String nameToLookup = originalBeanName(name); 35 if (args != null) { 36 // Delegation to parent with explicit args. 37 return (T) parentBeanFactory.getBean(nameToLookup, args); 38 } 39 else { 40 // No args -> delegate to standard getBean method. 41 return parentBeanFactory.getBean(nameToLookup, requiredType); 42 } 43 } 44 45 if (!typeCheckOnly) { 46 markBeanAsCreated(beanName); 47 } 48 49 try { 50 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 51 checkMergedBeanDefinition(mbd, beanName, args); 52 53 // Guarantee initialization of beans that the current bean depends on. 54 String[] dependsOn = mbd.getDependsOn(); 55 if (dependsOn != null) { 56 for (String dep : dependsOn) { 57 if (isDependent(beanName, dep)) { 58 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 59 "Circular depends-on relationship between ‘" + beanName + "‘ and ‘" + dep + "‘"); 60 } 61 registerDependentBean(dep, beanName); 62 getBean(dep); 63 } 64 } 65 66 // Create bean instance. 67 if (mbd.isSingleton()) { 68 sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { 69 @Override 70 public Object getObject() throws BeansException { 71 try { 72 return createBean(beanName, mbd, args); 73 } 74 catch (BeansException ex) { 75 // Explicitly remove instance from singleton cache: It might have been put there 76 // eagerly by the creation process, to allow for circular reference resolution. 77 // Also remove any beans that received a temporary reference to the bean. 78 destroySingleton(beanName); 79 throw ex; 80 } 81 } 82 }); 83 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); 84 } 85 86 else if (mbd.isPrototype()) { 87 // It‘s a prototype -> create a new instance. 88 Object prototypeInstance = null; 89 try { 90 beforePrototypeCreation(beanName); 91 prototypeInstance = createBean(beanName, mbd, args); 92 } 93 finally { 94 afterPrototypeCreation(beanName); 95 } 96 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); 97 } 98 99 else { 100 String scopeName = mbd.getScope(); 101 final Scope scope = this.scopes.get(scopeName); 102 if (scope == null) { 103 throw new IllegalStateException("No Scope registered for scope name ‘" + scopeName + "‘"); 104 } 105 try { 106 Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() { 107 @Override 108 public Object getObject() throws BeansException { 109 beforePrototypeCreation(beanName); 110 try { 111 return createBean(beanName, mbd, args); 112 } 113 finally { 114 afterPrototypeCreation(beanName); 115 } 116 } 117 }); 118 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); 119 } 120 catch (IllegalStateException ex) { 121 throw new BeanCreationException(beanName, 122 "Scope ‘" + scopeName + "‘ is not active for the current thread; consider " + 123 "defining a scoped proxy for this bean if you intend to refer to it from a singleton", 124 ex); 125 } 126 } 127 } 128 catch (BeansException ex) { 129 cleanupAfterBeanCreationFailure(beanName); 130 throw ex; 131 } 132 } 133 134 // Check if required type matches the type of the actual bean instance. 135 if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) { 136 try { 137 return getTypeConverter().convertIfNecessary(bean, requiredType); 138 } 139 catch (TypeMismatchException ex) { 140 if (logger.isDebugEnabled()) { 141 logger.debug("Failed to convert bean ‘" + name + "‘ to required type ‘" + 142 ClassUtils.getQualifiedName(requiredType) + "‘", ex); 143 } 144 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); 145 } 146 } 147 return (T) bean; 148 }
第5行对beanName进行了转换,因为我们传进去的参数可能是别名。
第9行对非懒加载的bean进行实例化。
第55行对依赖进行判断,如果有依赖还要进行循环依赖判断,构造器循环依赖是无法解决的会直接抛出异常,setter方法依赖就不会。
1 // Create bean instance. 2 if (mbd.isSingleton()) { 3 sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { 4 @Override 5 public Object getObject() throws BeansException { 6 try { 7 return createBean(beanName, mbd, args); 8 } 9 catch (BeansException ex) { 10 // Explicitly remove instance from singleton cache: It might have been put there 11 // eagerly by the creation process, to allow for circular reference resolution. 12 // Also remove any beans that received a temporary reference to the bean. 13 destroySingleton(beanName); 14 throw ex; 15 } 16 } 17 }); 18 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); 19 }
第3行
1 public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { 2 Assert.notNull(beanName, "‘beanName‘ must not be null"); 3 synchronized (this.singletonObjects) { 4 Object singletonObject = this.singletonObjects.get(beanName); 5 if (singletonObject == null) { 6 if (this.singletonsCurrentlyInDestruction) { 7 throw new BeanCreationNotAllowedException(beanName, 8 "Singleton bean creation not allowed while singletons of this factory are in destruction " + 9 "(Do not request a bean from a BeanFactory in a destroy method implementation!)"); 10 } 11 if (logger.isDebugEnabled()) { 12 logger.debug("Creating shared instance of singleton bean ‘" + beanName + "‘"); 13 } 14 beforeSingletonCreation(beanName); 15 boolean newSingleton = false; 16 boolean recordSuppressedExceptions = (this.suppressedExceptions == null); 17 if (recordSuppressedExceptions) { 18 this.suppressedExceptions = new LinkedHashSet<Exception>(); 19 } 20 try { 21 singletonObject = singletonFactory.getObject(); 22 newSingleton = true; 23 } 24 catch (IllegalStateException ex) { 25 // Has the singleton object implicitly appeared in the meantime -> 26 // if yes, proceed with it since the exception indicates that state. 27 singletonObject = this.singletonObjects.get(beanName); 28 if (singletonObject == null) { 29 throw ex; 30 } 31 } 32 catch (BeanCreationException ex) { 33 if (recordSuppressedExceptions) { 34 for (Exception suppressedException : this.suppressedExceptions) { 35 ex.addRelatedCause(suppressedException); 36 } 37 } 38 throw ex; 39 } 40 finally { 41 if (recordSuppressedExceptions) { 42 this.suppressedExceptions = null; 43 } 44 afterSingletonCreation(beanName); 45 } 46 if (newSingleton) { 47 addSingleton(beanName, singletonObject); 48 } 49 } 50 return (singletonObject != NULL_OBJECT ? singletonObject : null); 51 } 52 }
第四行先冲到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。
1 protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException { 2 if (logger.isDebugEnabled()) { 3 logger.debug("Creating instance of bean ‘" + beanName + "‘"); 4 } 5 RootBeanDefinition mbdToUse = mbd; 6 7 // Make sure bean class is actually resolved at this point, and 8 // clone the bean definition in case of a dynamically resolved Class 9 // which cannot be stored in the shared merged bean definition. 10 Class<?> resolvedClass = resolveBeanClass(mbd, beanName); 11 if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { 12 mbdToUse = new RootBeanDefinition(mbd); 13 mbdToUse.setBeanClass(resolvedClass); 14 } 15 16 // Prepare method overrides. 17 try { 18 mbdToUse.prepareMethodOverrides(); 19 } 20 catch (BeanDefinitionValidationException ex) { 21 throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), 22 beanName, "Validation of method overrides failed", ex); 23 } 24 25 try { 26 // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. 27 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); 28 if (bean != null) { 29 return bean; 30 } 31 } 32 catch (Throwable ex) { 33 throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, 34 "BeanPostProcessor before instantiation of bean failed", ex); 35 } 36 37 Object beanInstance = doCreateBean(beanName, mbdToUse, args); 38 if (logger.isDebugEnabled()) { 39 logger.debug("Finished creating instance of bean ‘" + beanName + "‘"); 40 } 41 return beanInstance; 42 }
第10行获取这个BeanDefinition内持有的class对象,所以这里是AspectJAwareAdvisorAutoProxyCreator类的class对象
第18行是准备方法覆盖,这个一般在使用了lookup-method,replace-method的时候使用。这里明显为空
第27行检查是否实现了InstantiationAwareBeanPostProcessor
接口,如果是,这里会调用实现的postProcessBeforeInstantiation方法。
第37行方法中调用了instanceWrapper = createBeanInstance(beanName, mbd, args);方法
1 protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) { 2 // Make sure bean class is actually resolved at this point. 3 Class<?> beanClass = resolveBeanClass(mbd, beanName); 4 5 if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { 6 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 7 "Bean class isn‘t public, and non-public access not allowed: " + beanClass.getName()); 8 } 9 10 if (mbd.getFactoryMethodName() != null) { 11 return instantiateUsingFactoryMethod(beanName, mbd, args); 12 } 13 14 // Shortcut when re-creating the same bean... 15 boolean resolved = false; 16 boolean autowireNecessary = false; 17 if (args == null) { 18 synchronized (mbd.constructorArgumentLock) { 19 if (mbd.resolvedConstructorOrFactoryMethod != null) { 20 resolved = true; 21 autowireNecessary = mbd.constructorArgumentsResolved; 22 } 23 } 24 } 25 if (resolved) { 26 if (autowireNecessary) { 27 return autowireConstructor(beanName, mbd, null, null); 28 } 29 else { 30 return instantiateBean(beanName, mbd); 31 } 32 } 33 34 // Need to determine the constructor... 35 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); 36 if (ctors != null || 37 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || 38 mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { 39 return autowireConstructor(beanName, mbd, ctors, args); 40 } 41 42 // No special handling: simply use no-arg constructor. 43 return instantiateBean(beanName, mbd); 44 }
第5行判断这个bean是不是public的,有没有访问权限,没有就抛异常
第10行是判断它是否有工厂方法,如果有工厂方法,就用工厂方法创建对象。
第35确定其是否需要构造器注入,如果是的话,那么会执行第39行,构造器注入的方式,否则直接到第43行,用无参构造器处理
进入这个instantiateBean方法
1 protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) { 2 try { 3 Object beanInstance; 4 final BeanFactory parent = this; 5 if (System.getSecurityManager() != null) { 6 beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() { 7 @Override 8 public Object run() { 9 return getInstantiationStrategy().instantiate(mbd, beanName, parent); 10 } 11 }, getAccessControlContext()); 12 } 13 else { 14 beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent); 15 } 16 BeanWrapper bw = new BeanWrapperImpl(beanInstance); 17 initBeanWrapper(bw); 18 return bw; 19 } 20 catch (Throwable ex) { 21 throw new BeanCreationException( 22 mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); 23 } 24 }
第14行getInstantiationStrategy()获取实例化策略,有SimpleInstantiationStrategy,CglibSubclassingInstantiationStrategy策略
这里我们假设是CglibSubclassingInstantiationStrategy策略,接下来调用了这个策略的instantiate方法,我们这里使用的CglibSubclassingInstantiationStrategy策略。进去看看吧
1 public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) { 2 // Don‘t override the class with CGLIB if no overrides. 3 if (bd.getMethodOverrides().isEmpty()) { 4 Constructor<?> constructorToUse; 5 synchronized (bd.constructorArgumentLock) { 6 constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod; 7 if (constructorToUse == null) { 8 final Class<?> clazz = bd.getBeanClass(); 9 if (clazz.isInterface()) { 10 throw new BeanInstantiationException(clazz, "Specified class is an interface"); 11 } 12 try { 13 if (System.getSecurityManager() != null) { 14 constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() { 15 @Override 16 public Constructor<?> run() throws Exception { 17 return clazz.getDeclaredConstructor((Class[]) null); 18 } 19 }); 20 } 21 else { 22 constructorToUse = clazz.getDeclaredConstructor((Class[]) null); 23 } 24 bd.resolvedConstructorOrFactoryMethod = constructorToUse; 25 } 26 catch (Throwable ex) { 27 throw new BeanInstantiationException(clazz, "No default constructor found", ex); 28 } 29 } 30 } 31 return BeanUtils.instantiateClass(constructorToUse); 32 } 33 else { 34 // Must generate CGLIB subclass. 35 return instantiateWithMethodInjection(bd, beanName, owner); 36 } 37 }
第9行判断这个类是不是接口,如果是接口,那就要报错,不能实例化
第22行获取到这个class的无参构造器
第31行代码
1 public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException { 2 Assert.notNull(ctor, "Constructor must not be null"); 3 try { 4 ReflectionUtils.makeAccessible(ctor); 5 return ctor.newInstance(args); 6 } 7 catch (InstantiationException ex) { 8 throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex); 9 } 10 catch (IllegalAccessException ex) { 11 throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex); 12 } 13 catch (IllegalArgumentException ex) { 14 throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex); 15 } 16 catch (InvocationTargetException ex) { 17 throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException()); 18 } 19 }
第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)方法
1 public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { 2 Object cacheKey = getCacheKey(beanClass, beanName); 3 4 if (beanName == null || !this.targetSourcedBeans.contains(beanName)) { 5 if (this.advisedBeans.containsKey(cacheKey)) { 6 return null; 7 } 8 if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { 9 this.advisedBeans.put(cacheKey, Boolean.FALSE); 10 return null; 11 } 12 } 13 14 // Create proxy here if we have a custom TargetSource. 15 // Suppresses unnecessary default instantiation of the target bean: 16 // The TargetSource will handle target instances in a custom fashion. 17 if (beanName != null) { 18 TargetSource targetSource = getCustomTargetSource(beanClass, beanName); 19 if (targetSource != null) { 20 this.targetSourcedBeans.add(beanName); 21 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); 22 Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); 23 this.proxyTypes.put(cacheKey, proxy.getClass()); 24 return proxy; 25 } 26 } 27 28 return null; 29 }
重点看到第8行shouldSkip方法
1 protected boolean shouldSkip(Class<?> beanClass, String beanName) { 2 // TODO: Consider optimization by caching the list of the aspect names 3 List<Advisor> candidateAdvisors = findCandidateAdvisors(); 4 for (Advisor advisor : candidateAdvisors) { 5 if (advisor instanceof AspectJPointcutAdvisor) { 6 if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) { 7 return true; 8 } 9 } 10 } 11 return super.shouldSkip(beanClass, beanName); 12 }
第三行表示去获取候选的通知器。调用了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看看
1 // Create proxy if we have advice. 2 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); 3 if (specificInterceptors != DO_NOT_PROXY) { 4 this.advisedBeans.put(cacheKey, Boolean.TRUE); 5 Object proxy = createProxy( 6 bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); 7 this.proxyTypes.put(cacheKey, proxy.getClass()); 8 return proxy; 9 }
进入第2行代码
1 protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) { 2 List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); 3 if (advisors.isEmpty()) { 4 return DO_NOT_PROXY; 5 } 6 return advisors.toArray(); 7 }
第2行代码通过当前类和类名寻找匹配的通知器
findEligibleAdvisors:
1 protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { 2 List<Advisor> candidateAdvisors = findCandidateAdvisors(); 3 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); 4 extendAdvisors(eligibleAdvisors); 5 if (!eligibleAdvisors.isEmpty()) { 6 eligibleAdvisors = sortAdvisors(eligibleAdvisors); 7 } 8 return eligibleAdvisors; 9 }
第二行获取到了所有候选的通知器
第三行获取到匹配当前bean的通知器
内部调用了AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);这个方法
内部又调用了canApply(pca.getPointcut(), targetClass, hasIntroductions);方法
1 for (Class<?> clazz : classes) { 2 Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz); 3 for (Method method : methods) { 4 if ((introductionAwareMethodMatcher != null && 5 introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) || 6 methodMatcher.matches(method, targetClass)) { 7 return true; 8 } 9 } 10 }
通过反射拿到当前类的所有方法,使用一个方法匹配器去配置当前方法是否可以匹配切点
如果匹配将对应的通知器保存起来,最后返回回到下面一段代码
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
最后我们看到createAopProxy犯法,这个方法的代码
1 public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { 2 if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { 3 Class<?> targetClass = config.getTargetClass(); 4 if (targetClass == null) { 5 throw new AopConfigException("TargetSource cannot determine target class: " + 6 "Either an interface or a target is required for proxy creation."); 7 } 8 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { 9 return new JdkDynamicAopProxy(config); 10 } 11 return new ObjenesisCglibAopProxy(config); 12 } 13 else { 14 return new JdkDynamicAopProxy(config); 15 } 16 }
第8行判断它是否实现了接口,如果实现了接口,那么就使用JDK的动态代理
否则使用第11行的cglib代理
接下类调用了getProxy方法,里面是我们属性代理创建过程,这里拿cglib为例
1 // Configure CGLIB Enhancer... 2 Enhancer enhancer = createEnhancer(); 3 if (classLoader != null) { 4 enhancer.setClassLoader(classLoader); 5 if (classLoader instanceof SmartClassLoader && 6 ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) { 7 enhancer.setUseCache(false); 8 } 9 } 10 enhancer.setSuperclass(proxySuperClass); 11 enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); 12 enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); 13 enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader)); 14 15 Callback[] callbacks = getCallbacks(rootClass); 16 Class<?>[] types = new Class<?>[callbacks.length]; 17 for (int x = 0; x < types.length; x++) { 18 types[x] = callbacks[x].getClass(); 19 } 20 // fixedInterceptorMap only populated at this point, after getCallbacks call above 21 enhancer.setCallbackFilter(new ProxyCallbackFilter( 22 this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); 23 enhancer.setCallbackTypes(types); 24 25 // Generate the proxy class and create a proxy instance. 26 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。
1 public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException { 2 List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3); 3 Advice advice = advisor.getAdvice(); 4 if (advice instanceof MethodInterceptor) { 5 interceptors.add((MethodInterceptor) advice); 6 } 7 for (AdvisorAdapter adapter : this.adapters) { 8 if (adapter.supportsAdvice(advice)) { 9 interceptors.add(adapter.getInterceptor(advisor)); 10 } 11 } 12 if (interceptors.isEmpty()) { 13 throw new UnknownAdviceTypeException(advisor.getAdvice()); 14 } 15 return interceptors.toArray(new MethodInterceptor[interceptors.size()]); 16 }
将所有的通知都打包成interceptor之后变成数组返回
MethodInterceptor接口只有一个方法Object invoke(MethodInvocation invocation) throws Throwable;
拿其中一个MethodBeforeAdviceInterceptor方法分析一下他的invoke方法
1 public Object invoke(MethodInvocation mi) throws Throwable { 2 this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() ); 3 return mi.proceed(); 4 }
第2行表示在执行目标方法前执行了这个通知类方法
当给每一个方法确定了匹配的通知拦截器后,准备工作也就完成了。
当我们去BeanFactory获取对象的时候,比如我们获取的是一个叫做UserService的类,这个service被应用了aop,所以很显然我们获取到的是一个代理类
我们用这个代理类去调用一个被增强的方法
加入代码是这样写的UserService service = beanFactory.getBean(UserService.class);
service.save();
从这里开始
当调用了这个方法后我们进入了一个DynamicAdvisedInterceptor类的intercept方法
1 public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { 2 Object oldProxy = null; 3 boolean setProxyContext = false; 4 Class<?> targetClass = null; 5 Object target = null; 6 try { 7 if (this.advised.exposeProxy) { 8 // Make invocation available if necessary. 9 oldProxy = AopContext.setCurrentProxy(proxy); 10 setProxyContext = true; 11 } 12 // May be null. Get as late as possible to minimize the time we 13 // "own" the target, in case it comes from a pool... 14 target = getTarget(); 15 if (target != null) { 16 targetClass = target.getClass(); 17 } 18 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); 19 Object retVal; 20 // Check whether we only have one InvokerInterceptor: that is, 21 // no real advice, but just reflective invocation of the target. 22 if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) { 23 // We can skip creating a MethodInvocation: just invoke the target directly. 24 // Note that the final invoker must be an InvokerInterceptor, so we know 25 // it does nothing but a reflective operation on the target, and no hot 26 // swapping or fancy proxying. 27 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); 28 retVal = methodProxy.invoke(target, argsToUse); 29 } 30 else { 31 // We need to create a method invocation... 32 retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed(); 33 } 34 retVal = processReturnType(proxy, target, method, retVal); 35 return retVal; 36 } 37 finally { 38 if (target != null) { 39 releaseTarget(target); 40 } 41 if (setProxyContext) { 42 // Restore old proxy. 43 AopContext.setCurrentProxy(oldProxy); 44 } 45 } 46 }
第14行获取目标代理类
第18行获取符合代理目标的拦截器链。也就是一个集合装了一堆符合条件的拦截器,比如前置通知拦截器,后置通知拦截器
第32行创建一个CglibMethodInvocation的实例,并且调用它的proceed方法
1 public Object proceed() throws Throwable { 2 // We start with an index of -1 and increment early. 3 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { 4 return invokeJoinpoint(); 5 } 6 7 Object interceptorOrInterceptionAdvice = 8 this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); 9 if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { 10 // Evaluate dynamic method matcher here: static part will already have 11 // been evaluated and found to match. 12 InterceptorAndDynamicMethodMatcher dm = 13 (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; 14 if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { 15 return dm.interceptor.invoke(this); 16 } 17 else { 18 // Dynamic matching failed. 19 // Skip this interceptor and invoke the next in the chain. 20 return proceed(); 21 } 22 } 23 else { 24 // It‘s an interceptor, so we just invoke it: The pointcut will have 25 // been evaluated statically before this object was constructed. 26 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); 27 } 28 }
第3行代码查看当前下标和当前拦截器链的个数减一是否相等了,如果相等了,那么就调用被代理的目标方法,
这里使用了一个currentInterceptorIndex来表示当前已经调用到了哪个拦截器
第8行获取当前下标的拦截器 ,并且调用它的invoke方法,把自身也传进去
假设当前的拦截器是AspectJAfterAdvice拦截器,那么它的invoke方法如下
1 public Object invoke(MethodInvocation mi) throws Throwable { 2 try { 3 return mi.proceed(); 4 } 5 finally { 6 invokeAdviceMethod(getJoinPointMatch(), null, null); 7 } 8 }
在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(四)