spring aop过程分析

本文详细分析了Spring AOP的代理过程,包括在bean初始化完成后如何通过BeanPostProcessor进行后置处理,判断是否需要代理,以及使用AbstractAutoProxyCreator和AbstractAdvisingBeanPostProcessor的差别。内容涉及cglib和jdk动态代理的生成机制,阐述了代理类如何在调用时被拦截。
摘要由CSDN通过智能技术生成

额。。。终于艰难的把整个aop和部分ioc初始化过程捋了遍。。。

总结

1.在 bean初始化完成,加入到spring ioc容器之前,会调用BeanPostProcessors执行后置动作
2.其中会调用自动代理生成器(AbstractAutoProxyCreator)或者其他的自定义代理生成(AbstractAdvisingBeanPostProcessor子类)来判断(类、方法)、生成代理类,最后替换掉原来的bean放入到容器中
3.因此,通过ioc容器注入依赖的类,实际注入的是代理类(如果有的话),在调用代理类的时候,会被拦截(cglib的MethodInterceptor,jdk动态代理的InvocationHandler),调用Advisor方法

aop代理类的生成

总结

其实总的来说并不复杂,就是在初始化上下文加载bean的时候,判断该bean是否需要代理,如果需要则生成代理类,把代理类存放到容器中,然后需要注入该bean的时候,实际注入的是代理类

流程:

下面逐一讲解下各个流程

1.spring启动、初始化上下文

整个加载bean的过程基本是在AbstractApplicationContext#refresh方法中执行,然后在加载完BeanFactory,PostProcessors后,调用finishBeanFactoryInitialization来加载剩余bean,也就是我们定义的bean

public void refresh() throws BeansException, IllegalStateException {
   
		...
		// Allows post-processing of the bean factory in context subclasses.
         postProcessBeanFactory(beanFactory);

         // Invoke factory processors registered as beans in the context.
         invokeBeanFactoryPostProcessors(beanFactory);

         // Register bean processors that intercept bean creation.
         registerBeanPostProcessors(beanFactory);

         // Initialize message source for this context.
         initMessageSource();

         // Initialize event multicaster for this context.
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         onRefresh();

         // Check for listener beans and register them.
         registerListeners();

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

         // Last step: publish corresponding event.
         finishRefresh();
         ...
}

2.bean的加载

DefaultListableBeanFactory#preInstantiateSingletons
AbstractBeanFactory#getBean
AbstractBeanFactory#doGetBean
DefaultSingletonBeanRegistry#getSingleton
AbstractAutowireCapableBeanFactory#createBean
AbstractAutowireCapableBeanFactory#doCreateBean
AbstractAutowireCapableBeanFactory#initializeBean

在经过一些列的方法后,终于把bean初始化完成(其中过程过于复杂。。。艰辛)
在这里插入图片描述
bean初始化完成后,调用AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization,其中会调用BeanPostProcessor#postProcessAfterInitialization对bean进行后置的处理

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException {
   

   Object result = existingBean;
   for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
   
      result = beanProcessor.postProcessAfterInitialization(result, beanName);
      if (result == null) {
   
         return result;
      }
   }
   return result;
}

3.aop相关的BeanPostProcessor对bean进行处理

跟aop相关的BeanPostProcessor是AbstractAdvisingBeanPostProcessor其子类和AbstractAutoProxyCreator,这两类主要差别是在判断是否需要代理,换句话说,就是各自负责不同的类型的代理

3.1判断是否需要代理

总结

通过自动生成代理的走AbstractAutoProxyCreator,而一些需要特殊处理的走AbstractAdvisingBeanPostProcessor子类

都是通过判断类及所有方法是否有匹配的Advisor(根据Poincut带的ClassFilter和MethodMatcher),来决定是否需要代理

AbstractAutoProxyCreator

总结

核心方法是下面wrapIfNecessary中的getAdvicesAndAdvisorsForBean,会去根据bean的名字、类型去获取相应的通知,而这个方法在spring有2种实现(下图也可以看到druid自己实现来创建自己的代理类)

其中一种BeanNameAutoProxyCreator,是通过名字匹配(左右模糊、精确),功能比较简单

而另一种的AbstractAdvisorAutoProxyCreator,通过实现ClassFilter和MethodMatcher来实现各种的匹配方法(如:AnnotationMethodMatcher就用于AnnotationMatchingPointcut,针对注解的判断,@Async注解就是用的这个切面类)。平时手动创建的Pointcut等都是由该类处理
getAdvicesAndAdvisorsForBean实现

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

	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
   
		...

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

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

下面看下这两种不同的实现是怎样:

BeanNameAutoProxyCreator

其实从名字可以看出,大概就是通过名字来查询匹配,从下面核心匹配方法 isMatch 的注释可以看到,通过名字匹配,匹配规则是右模糊(xxx*)、左模糊(*xxx)、以及精确匹配(xxx),比较简单的一个匹配方法

protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
   
		if (this.beanNames != null) {
   
			for (String mappedName : this.beanNames) {
   
				if (FactoryBean.class.isAssignableFrom(beanClass)) {
   
					if (!mappedName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
   
						continue;
					}
					mappedName = mappedName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
				}
				if (isMatch(beanName, mappedName)) {
   
					return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
				}
				BeanFactory beanFactory = getBeanFactory();
				if (beanFactory != null) {
   
					String[] aliases = beanFactory.getAliases(beanName);
					for (String alias : aliases) {
   
						if (isMatch(alias, mappedName)) {
   
							return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
						}
					}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值