springaop源码解读

XML配置使用springaop源码解读

提示:假设已经阅读过spring的源码



使用方法

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       //引入命名空间
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
//需要被通知的类,也是动态代理中的目标类
<bean id="person" class="com.srping.aop.Person"></bean>


	//通知类
    <bean id="myAdvice" class="com.srping.aop.MyAdvice"></bean>
	//<aop:config>,会告诉spring容器使用AopNameSpaceHandler解析其下面的子标签
    <aop:config>
       //<aop:aspect>解析此标签是会在spring容器中注册一个org.springframework.aop.aspectj.AspectJPointcutAdvisor
        <aop:aspect ref="myAdvice">
        //前置通知,配置通知的方法和切入点
        <aop:before method="log" pointcut="execution(void com.srping.aop.Person.eat())"/>
        </aop:aspect>
    </aop:config>
</beans>

源码阅读

AopNamespaceHandler.init()

public class AopNamespaceHandler extends NamespaceHandlerSupport {
    public AopNamespaceHandler() {
    }

    public void init() {
     //<aop:config>告诉spring容器使用ConfigBeanDefinitionParser解析子标签
        this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
        //注解方式使用springAOP是开启自动扫描@Aspect,不在本篇阅读范围
        this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
        this.registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
        this.registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
    }
}

ConfigBeanDefinitionParser.parse()

  @Nullable
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
        parserContext.pushContainingComponent(compositeDef);
        //向spring容器注册一个org.springframework.aop.config.internalAutoProxyCreator的BeanDefinition
        //,在getBean的时候会实例化一个org.springframework.aop.config.internalAutoProxyCreator,这是一个    //beanPostPorocessor,可以创建目标类的代理对象
        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)) {
            //解析<aop:aspect>,并且注册一个AspectJPointcutAdvisor到spring容器
                this.parseAspect(elt, parserContext);
            }
        }

        parserContext.popAndRegisterContainingComponent();
        return null;
    }

ConfigBeanDefinitionParser.parseAdvice()

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)));
            RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class);
            methodDefinition.getPropertyValues().add("targetBeanName", aspectName);
            //设置通知方法名
            methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method"));
            methodDefinition.setSynthetic(true);
            RootBeanDefinition aspectFactoryDef = new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class);
            aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName);
            aspectFactoryDef.setSynthetic(true);
            AbstractBeanDefinition adviceDef = this.createAdviceDefinition(adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef, beanDefinitions, beanReferences);
            RootBeanDefinition advisorDefinition = new RootBeanDefinition(AspectJPointcutAdvisor.class);
            advisorDefinition.setSource(parserContext.extractSource(adviceElement));
            advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef);
            if (aspectElement.hasAttribute("order")) {
                advisorDefinition.getPropertyValues().add("order", aspectElement.getAttribute("order"));
            }

            parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition);
            var12 = advisorDefinition;
        } finally {
            this.parseState.pop();
        }

        return var12;
    }

spring容器加载完成

在这里插入图片描述

getBean获取代理对象

//spring在populateBean之后会调用initializeBean方法,执行bean的init方法和bean的后置处理器(spring的源码知识点)
    protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(() -> {
                this.invokeAwareMethods(beanName, bean);
                return null;
            }, this.getAccessControlContext());
        } else {
            this.invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
        }

        try {
            this.invokeInitMethods(beanName, wrappedBean, mbd);
        } catch (Throwable var6) {
            throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
        }

        if (mbd == null || !mbd.isSynthetic()) {
        //这里调用AspectAwareAdvisorAutoProxyCreator的postProcessAfterInitialization方法
            wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }

AbstractAutoProxyCreator.wrapIfNecessary()

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        } else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        } else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
            Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
            if (specificInterceptors != DO_NOT_PROXY) {
                this.advisedBeans.put(cacheKey, Boolean.TRUE);
                **//最后创建person的代理对象**
                Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
                this.proxyTypes.put(cacheKey, proxy.getClass());
                return proxy;
            } else {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return bean;
            }
        } else {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }
    }

DefaultAopProxyFactory.createAopProxy()

 public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
 //是否开启cglib自动代理或者是否有实现接口来觉得是采用JDK的自动代理还是Cglib的自动代理
        if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
            return new JdkDynamicAopProxy(config);
        } else {
            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.");
            } else {
                return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
            }
        }
    }

总结

1.根据aop:config标签让spring容器加载beanDefinition的时候用AopNameSpaceHandler来解析
2.解析aop:advice时,会创建一个org.springframework.aop.aspectj.AspectJPointcutAdvisor#0对象,
对象有属性advice和pointcut,pointcut会根据配置文件的ponitcut表达式生成classFilter和methodMatch,后续会根据这个两个匹配器过滤哪些类和方法需要被代理和拦截
3.同时spring容器会注册一个AspectAwareAdvisorAutoProxyCreator的后置处理器
4.getBean时,会调用AspectAwareAdvisorAutoProxyCreator的后置处理方法返回代理对象

以上,仅代表个人阅读源码的理解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值