写点什么

Spring 源码解析(二)AOP,java 基础课程百度云

作者:Java高工P7
  • 2021 年 11 月 10 日
  • 本文字数:8072 字

    阅读完需:约 26 分钟

AOP 是什么




  • 面向切面编程

  • Spring 的两大特性之一

  • 是 OOP 的重要补充


AOP 有什么用




  • 代码解耦

  • 关注横向关系

  • 分离核心业务和非核心业务

  • 应用场景有:事务管理、缓存管理、日志收集、权限控制、性能监控等


AOP 有哪些概念




  • Aspect(切面) 哪些方法会被切中,切中后如何处理

  • PointCut(切入点)定义哪些方法被切中,Java 的 AOP 只支持方法,其他语言可以支持构造方法或属性

  • JoinPoint(连接点)被切中的方法

  • Advise(通知)在原有方法的基础上,加入新的功能

  • 前置 before

  • 后置 after

  • 环绕 around

  • 返回后置 afterReturning

  • 异常后置 afterThrowing

  • Weave(织入)在原有方法的功能上,加入新功能过程


AOP 的实现原理





源码解析


==================================================================


解析源码需要带着目的来看,这次主要看两个重点:


  1. aop 有关的标签是如何解析并注册到 IOC 容器中的

  2. 获得 JavaBean 时是如何产生动态代理的


接下来我们看看 Spring 源码中进行 AOP 的过程,首先我们要找到 AOP 的入口。


这不像 IOC 的源码有具体的类和方法可以直接进入,AOP 是自动进行的,它是在哪里导入到 Spring 中的呢?


我们可以回想一下 IOC 的过程:


有一个步骤是分别解析默认的命名空间和自定义的命名空间,aop 就属于自定义命名空间,会不会在这里 Spring 做了特殊的处理?


我们从这个位置进入看看:


DefaultBeanDefinitionDocumentReader 类:


protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {


if (delegate.isDefaultNamespace(root)) {


NodeList nl = root.getChildNodes();


for(int i = 0; i < nl.getLength(); ++i) {


Node node = nl.item(i);


if (node instanceof Element) {


Element ele = (Element)node;


if (delegate.isDefaultNamespace(ele)) {


//解析默认命名空间


this.parseDefaultElement(ele, delegate);


} else {


delegate.parseCustomElement(ele);


}


}


}


} else {


//解析自定义命名空间


delegate.parseCustomElement(root);


}


}


进入解析自定义命名空间的方法,首先是拿到元素的 URI,对于 AOP 就是http://www.springframework.org/schema/aop,然后通过 URI 找到对应的命名空间处理器 NamespaceHandler,对应 AOP 的处理器就是 AOPNamespaceHandler,然后由处理器来进行解析。


BeanDefinitionParserDelegate 类:


public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {


//获得 Element 的 URI


String namespaceUri = this.getNamespaceURI(ele);


//通过 URI 找到处理器


NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);


if (handler == null) {


this.error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);


return null;


} else {


//解析 XML 元素


return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));


}


}


看下 AopNamespaceHandler 类


public class AopNamespaceHandler extends NamespaceHandlerSupport {


public AopNamespaceHandler() {


}


public void init() {


this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());


this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());


this.registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());


this.registerBean


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


DefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());


}


}


它实际上就是注册了四个解析器来处理四种 aop 标签:


  • config ConfigBeanDefinitionParser

  • aspectj-autoproxy AspectJAutoProxyBeanDefinitionParser

  • scoped-proxy ScopedProxyBeanDefinitionDecorator

  • spring-configured SpringConfiguredBeanDefinitionParser


我们最常用的是 aop:config 标签,接下来我们看看 ConfigBeanDefinitionParser 类


这个类中主要有个 parse 方法,第一个参数是 XML 元素,第二个是解析器上下文


public BeanDefinition parse(Element element, ParserContext parserContext) {


CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));


parserContext.pushContainingComponent(compositeDef);


this.configureAutoProxyCreator(parserContext, element);


List<Element> childElts = DomUtils.getChildElements(element);


Iterator var5 = childElts.iterator();


while(var5.hasNext()) {


Element elt = (Element)var5.next();


String localName = parserContext.getDelegate().getLocalName(elt);


if ("pointcut".equals(localName)) {


this.parsePointcut(elt, parserContext);


} else if ("advisor".equals(localName)) {


this.parseAdvisor(elt, parserContext);


} else if ("aspect".equals(localName)) {


this.parseAspect(elt, parserContext);


}


}


parserContext.popAndRegisterContainingComponent();


return null;


}


下面部分通过标签名称的判断,解析 config 标签中的 pointcut、advisor 和 aspect 这三个标签。先看看切面部分的解析:


private void parseAspect(Element aspectElement, ParserContext parserContext) {


//获得 aspect 的 id 和 name 值


String aspectId = aspectElement.getAttribute("id");


String aspectName = aspectElement.getAttribute("ref");


try {


this.parseState.push(new AspectEntry(aspectId, aspectName));


List<BeanDefinition> beanDefinitions = new ArrayList();


List<BeanReference> beanReferences = new ArrayList();


//获得已知的父类元素


List<Element> declareParents = DomUtils.getChildElementsByTagName(aspectElement, "declare-parents");


//解析所有的父类元素


for(int i = 0; i < declareParents.size(); ++i) {


Element declareParentsElement = (Element)declareParents.get(i);


beanDefinitions.add(this.parseDeclareParents(declareParentsElement, parserContext));


}


NodeList nodeList = aspectElement.getChildNodes();


boolean adviceFoundAlready = false;


//遍历所有子节点


for(int i = 0; i < nodeList.getLength(); ++i) {


Node node = nodeList.item(i);


//判断是否是 before、after、after-returning、after-throwing、around


if (this.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));


}


//解析每个 advice,并添加到集合中


AbstractBeanDefinition advisorDefinition = this.parseAdvice(aspectName, i, aspectElement, (Element)node, parserContext, beanDefinitions, beanReferences);


beanDefinitions.add(advisorDefinition);


}


}


AspectComponentDefinition aspectComponentDefinition = this.createAspectComponentDefinition(aspectElement, aspectId, beanDefinitions, beanReferences, parserContext);


parserContext.pushContainingComponent(aspectComponentDefinition);


List<Element> pointcuts = DomUtils.getChildElementsByTagName(aspectElement, "pointcut");


Iterator var21 = pointcuts.iterator();


//解析 aspect 中所有的 pointcut 子节点


while(var21.hasNext()) {


Element pointcutElement = (Element)var21.next();


this.parsePointcut(pointcutElement, parserContext);


}


//发送注册完成的事件


parserContext.popAndRegisterContainingComponent();


} finally {


this.parseState.pop();


}


}


在看看 Advice 的解析:


private AbstractBeanDefinition parseAdvice(String aspectName, int order,


Element aspectElement, Element adviceElement, ParserContext parserContext, List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {


RootBeanDefinition var12;


try {


//入栈一个解析状态


this.parseState.push(new AdviceEntry(parserContext.getDelegate().getLocalName(adviceElement)));


//创建 BeanDefinition,保存方法的信息


RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class);


methodDefinition.getPropertyValues().add("targetBeanName", aspectName);


methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method"));


methodDefinition.setSynthetic(true);


//创建 BeanDefinition,保存工厂信息


RootBeanDefinition aspectFactoryDef = new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class);


aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName);


aspectFactoryDef.setSynthetic(true);


//把前面解析出来的内容包装起来,创建一个 Advise 方法的 BeanDefinition


AbstractBeanDefinition adviceDef = this.createAdviceDefinition(adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef, beanDefinitions, beanReferences);


//所有内容最后放在这个 BeanDefinition 中


RootBeanDefinition advisorDefinition = new RootBeanDefinition(AspectJPointcutAdvisor.class);


advisorDefinition.setSource(parserContext.extractSource(adviceElement));


//将 Advice 的定义添加到 Advisor 的构造方法参数中


advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef);


//解析 aspect 的 order 属性


if (aspectElement.hasAttribute("order")) {


advisorDefinition.getPropertyValues().add("order", aspectElement.getAttribute("order"));


}


//在 IOC 容器中注册 Advisor 的 BeanDefinition


parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition);


var12 = advisorDefinition;


} finally {


this.parseState.pop();


}


return var12;


}


创建 Advise 定义的方法,这个方法把前面解析的一系列内容放到 BeanDefinition 中。


private AbstractBeanDefinition createAdviceDefinition(Element adviceElement, ParserContext parserContext, String aspectName, int order, RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef, List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {


//获得 Advise 的类型,并创建一个 BeanDefinition


RootBeanDefinition adviceDefinition = new RootBeanDefinition(this.getAdviceClass(adviceElement, parserContext));


adviceDefinition.setSource(parserContext.extractSource(adviceElement));


adviceDefinition.getPropertyValues().add("aspectName", aspectName);


adviceDefinition.getPropertyValues().add("declarationOrder", order);


if (adviceElement.hasAttribute("returning")) {


adviceDefinition.getPropertyValues().add("returningName", adviceElement.getAttribute("returning"));


}


if (adviceElement.hasAttribute("throwing")) {


adviceDefinition.getPropertyValues().add("throwingName", adviceElement.getAttribute("throwing"));


}


if (adviceElement.hasAttribute("arg-names")) {


adviceDefinition.getPropertyValues().add("argumentNames", adviceElement.getAttribute("arg-names"));


}


ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues();


cav.addIndexedArgumentValue(0, methodDef);


Object pointcut = this.parsePointcutProperty(adviceElement, parserContext);


if (pointcut instanceof BeanDefinition) {


cav.addIndexedArgumentValue(1, pointcut);


beanDefinitions.add((BeanDefinition)pointcut);


} else if (pointcut instanceof String) {


RuntimeBeanReference pointcutRef = new RuntimeBeanReference((String)pointcut);


cav.addIndexedArgumentValue(1, pointcutRef);


beanReferences.add(pointcutRef);


}


cav.addIndexedArgumentValue(2, aspectFactoryDef);


return adviceDefinition;


}


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".equals(elementName)) {


return AspectJAfterReturningAdvice.class;


} else if ("after-throwing".equals(elementName)) {


return AspectJAfterThrowingAdvice.class;


} else if ("around".equals(elementName)) {


return AspectJAroundAdvice.class;


} else {


throw new IllegalArgumentException("Unknown advice kind [" + elementName + "].");


}


}


到这里 aop:config 标签里的所有内容都被解析出来了,包装成 BeanDefinition,并注册到 IOC 的容器中了。


再看动态代理是如何产生的,所有的 Bean 包括代理,都可以通过 getBean 来获得,我们从这条线索跟下去:


AbstractApplicationContext 类:


public Object getBean(String name) throws BeansException {


this.assertBeanFactoryActive();


//这里


return this.getBeanFactory().getBean(name);


}


AbstractBeanFactory 类:


public Object getBean(String name) throws BeansException {


//这里


return this.doGetBean(name, (Class)null, (Object[])null, false);


}


跟进去


protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {


final String beanName = this.transformedBeanName(name);


Object sharedInstance = this.getSingleton(beanName);


Object bean;


if (sharedInstance != null && args == null) {


if (this.logger.isDebugEnabled()) {


if (this.isSingletonCurrentlyInCreation(beanName)) {


this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");


} else {


this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'");


}


}


//这里 获得 JavaBean 实例对象


bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);


} else {


...


}


}


跟进去


protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {


if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {


throw new BeanIsNotAFactoryException(this.transformedBeanName(name), beanInstance.getClass());


} else if (beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {


Object object = null;


if (mbd == null) {


object = this.getCachedObjectForFactoryBean(beanName);


}


if (object == null) {


FactoryBean<?> factory = (FactoryBean)beanInstance;


if (mbd == null && this.containsBeanDefinition(beanName)) {


mbd = this.getMergedLocalBeanDefinition(beanName);


}


boolean synthetic = mbd != null && mbd.isSynthetic();


//这里 通过工厂 Bean 获得对象


object = this.getObjectFromFactoryBean(factory, beanName, !synthetic);


}


return object;


} else {


return beanInstance;


}


}


跟进去


protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {


if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {


throw new BeanIsNotAFactoryException(this.transformedBeanName(name), beanInstance.getClass());


} else if (beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {


Object object = null;


if (mbd == null) {


object = this.getCachedObjectForFactoryBean(beanName);


}


if (object == null) {


FactoryBean<?> factory = (FactoryBean)beanInstance;


if (mbd == null && this.containsBeanDefinition(beanName)) {


mbd = this.getMergedLocalBeanDefinition(beanName);


}


boolean synthetic = mbd != null && mbd.isSynthetic();


//这里


object = this.getObjectFromFactoryBean(factory, beanName, !synthetic);


}


return object;


} else {


return beanInstance;


}


}


跟进去


protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {


if (factory.isSingleton() && this.containsSingleton(beanName)) {


synchronized(this.getSingletonMutex()) {


Object object = this.factoryBeanObjectCache.get(beanName);


if (object == null) {


// 这里


object = this.doGetObjectFromFactoryBean(factory, beanName);


Object alreadyThere = this.factoryBeanObjectCache.get(beanName);


if (alreadyThere != null) {


object = alreadyThere;


} else {


if (object != null && shouldPostProcess) {


try {


object = this.postProcessObjectFromFactoryBean(object, beanName);


} catch (Throwable var9) {


throw new BeanCreationException(beanName, "Post-processing of FactoryBean's singleton object failed", var9);


}


}


this.factoryBeanObjectCache.put(beanName, object != null ? object : NULL_OBJECT);


}


}


return object != NULL_OBJECT ? object : null;


}


} else {


Object object = this.doGetObjectFromFactoryBean(factory, beanName);


if (object != null && shouldPostProcess) {


try {


object = this.postProcessObjectFromFactoryBean(object, beanName);


} catch (Throwable var11) {


throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", var11);


}


}


return object;


}


}


跟进去


private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, String beanName) throws BeanCreationException {


Object object;


try {


if (System.getSecurityManager() != null) {


AccessControlContext acc = this.getAccessControlContext();


try {


object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {


public Object run() throws Exception {


return factory.getObject();


}


}, acc);


} catch (PrivilegedActionException var6) {


throw var6.getException();


}


} else {


//这里


object = factory.getObject();


}


} catch (FactoryBeanNotInitializedException var7) {


throw new BeanCurrentlyInCreationException(beanName, var7.toString());


} catch (Throwable var8) {


throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", var8);


}


if (object == null && this.isSingletonCurrentlyInCreation(beanName)) {


throw new BeanCurrentlyInCreationException(beanName, "FactoryBean which is currently in creation returned null from getObject");


} else {


return object;


}


}


这个 getObject 就是从工厂中拿到对象了,FactoryBean 有很多种实现类,我们往下跟 ProxyFactoryBean 也就是代理的工厂 Bean。


ProxyFactoryBean


public Object getObject() throws BeansException {

用户头像

Java高工P7

关注

还未添加个人签名 2021.11.08 加入

还未添加个人简介

评论

发布
暂无评论
Spring源码解析(二)AOP,java基础课程百度云