IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 一文吃透spring aop底层原理 -> 正文阅读

[Java知识库]一文吃透spring aop底层原理

前言

看这一遍默认你对spring aop使用非常了解,对动态代理也有一定的了解,如果确实不是很了解请看下面的几篇使用相关的文档
spring 学习之四(spring的注入方式(xml和annotation))

spring学习之五(spring aop编程)

回顾ioc容器 初始化过程

在这里插入图片描述
aop其实就是对我们目前的方法进行增强,根据我们以前的知识储备知道 AnnotationAwareAspectJAutoProxyCreator这个类是aop实现的一个比较核心的一个类,这个类也是一个BeanPostProcessor类,这样根据我们对ioc容器初始化就比较容易理解了,
1.在beanBactory初始化过程中将BeanPoster注册到BeanDefinitionMap中
2. Bean在初始化时进行对bean增强, 也就是在init方法前后进行操作

从@EnableAspectJAutoProxy看起

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

	/**
	 * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
	 * to standard Java interface-based proxies. The default is {@code false}.
	 */
	boolean proxyTargetClass() default false;

	/**
	 * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
	 * for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
	 * Off by default, i.e. no guarantees that {@code AopContext} access will work.
	 * @since 4.3.1
	 */
	boolean exposeProxy() default false;

}

@Import(AspectJAutoProxyRegistrar.class) 这个我们知道导入了一个注册类AspectJAutoProxyRegistrar组件

@Import 注解源码参考

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	/**
	 * Register, escalate, and configure the AspectJ auto proxy creator based on the value
	 * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
	 * {@code @Configuration} class.
	 */
	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		if (enableAspectJAutoProxy != null) {
			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}

}

这个方法就是处理我们在使用@EnableAspectJAutoProxy 中的两个属性( exposeProxy proxyTargetClass),默认两个都为false 先不深入了解这个了

@Nullable
	public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {

		return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
	}

此时将AnnotationAwareAspectJAutoProxyCreator 注册到beandefinitionmap中

@Nullable
	private static BeanDefinition registerOrEscalateApcAsRequired(
			Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
			BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
				int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
				int requiredPriority = findPriorityForClass(cls);
				if (currentPriority < requiredPriority) {
					apcDefinition.setBeanClassName(cls.getName());
				}
			}
			return null;
		}

		RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
		beanDefinition.setSource(source);
		beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
		beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
		return beanDefinition;
	}

IOC容器中注入了一个internalAutoProxyCreator=AnnotationAwareAspectJAutoProxyCreator的beandefintion,到此可以得出结论,@EnableAspectJAutoProxy给容器中注册一个AnnotationAwareAspectJAutoProxyCreator。

AnnotationAwareAspectJAutoProxyCreator 上下继承关系如下

我们从下图可以知道继承接口BeanFactoryAware 和BeanPostProcessor接口因此我们可以知道在bean初始化时回出发
在这里插入图片描述
 在此需要关注两点内容:

1)关注后置处理器SmartInstantiationAwareBeanPostProcessor(在bean初始化完成前后做事情)

2)关注自动装配BeanFactory。

通过代码查看,发现父类AbstractAutoProxyCreator中有后置处理器的内容;AbstactAdvisorAutoProxyCreator类中重写了其父类AbstractAutoProxyCreator中setBeanFactory()方法,在AnnotationAwareAspectJAutoProxyCreator类中initBeanFactory()方法完成了自动装配BeanFactory。分别在这两处关注点打断点来查看其流程:
我们知道AbstactAdvisorAutoProxyCreator 初始化时的一个大致过程如下:

在这里插入图片描述

setBeanFactory方法和BeanPostProcessorsBeforeInitialization BeanPostProcessorsAfterInitialization 顺序如下图
在这里插入图片描述
源码逻辑:

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else { // 执行aware 中的方法
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			//BeanPostProcessor Before方法
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			// init 方法 @PostConstruct init指定方法 InitializingBean等方式
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
			//beanPostProcessor after方法
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

invokeAwareMethods

该方法比较简单:

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#setBeanFactory
@Override
	public void setBeanFactory(BeanFactory beanFactory) {
		super.setBeanFactory(beanFactory);
		if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
			throw new IllegalArgumentException(
					"AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
		}
		initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
	}
	protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
	}
	子类重写了initBeanFactory方法
@Override
	protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		super.initBeanFactory(beanFactory);
		if (this.aspectJAdvisorFactory == null) {
			this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
		}
		this.aspectJAdvisorsBuilder =
				new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
	}

applyBeanPostProcessorsBeforeInitialization

我看的5.3.x版本的spring 开始没重写 这个before方法

invokeInitMethods

实例化

applyBeanPostProcessorsAfterInitialization

此时看beanpostProcessor 工作原理

小结

1)、传入配置类,创建ioc容器
          2)、注册配置类,调用refresh()刷新容器;
          3)、registerBeanPostProcessors(beanFactory);注册bean的后置处理器来方便拦截bean的创建;
              1)、先获取ioc容器已经定义了的需要创建对象的所有BeanPostProcessor
              2)、给容器中加别的BeanPostProcessor
              3)、优先注册实现了PriorityOrdered接口的BeanPostProcessor4)、再给容器中注册实现了Ordered接口的BeanPostProcessor5)、注册没实现优先级接口的BeanPostProcessor6)、注册BeanPostProcessor,实际上就是创建BeanPostProcessor对象,保存在容器中;
                  创建internalAutoProxyCreator的BeanPostProcessorAnnotationAwareAspectJAutoProxyCreator1)、创建Bean的实例
                  2)、populateBean;给bean的各种属性赋值
                  3)、initializeBean:初始化bean;
                          1)、invokeAwareMethods():处理Aware接口的方法回调
                          2)、applyBeanPostProcessorsBeforeInitialization():应用后置处理器的postProcessBeforeInitialization()
                          3)、invokeInitMethods();执行自定义的初始化方法
                          4)、applyBeanPostProcessorsAfterInitialization();执行后置处理器的postProcessAfterInitialization();
                  4)、BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功;--》aspectJAdvisorsBuilder
              7)、把BeanPostProcessor注册到BeanFactory中;
                  beanFactory.addBeanPostProcessor(postProcessor);  =======以上是创建和注册AnnotationAwareAspectJAutoProxyCreator的过程========

aop创建对象原理

从上面我分析的逻辑和前置知识非常清楚,当我们自己编写的类填写@EnableAspectJAutoProxy或者通过其他方式开启aop都是在docreateBean方法中进行增强:

我们在这个方法入口打断点 使用断点的方式进行跟踪分析:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

exposedObject = initializeBean(beanName, exposedObject, mbd);

这个方法上面我都分析了aware相关的方法, before init after方法,由于 自己的类非aware ,因此不会执行, before没有重写, 因此不重要下面直接after方法
在这里插入图片描述
进来的时候实体对象不是代理对象,我们继续往下看从哪里开始处理成的代理对象的

beanpostProcessor 工作原理

从上面分析我们可以知道Spring入住了AnnotationAwareAspectJAutoProxyCreator 一个BeanPostProcessor类,又知道改类没有重写before方法,因此after方法才是我们的重点:

重写 beanpostprocessor的after方法

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization
@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

在这里插入图片描述
这个地方是二级缓存中存在,删除进行创建对象,ps:二级缓存中存放的是只进行实例化,没有进行初始化的对象

postProcessAfterInitialization方法会对切面进行一次包装的处理。

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

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

下面进行创建代理对象
第一步:创建代理对象的ProxyFactory 工厂
第二步:使用工厂模式创建代理对象

protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {

		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}

		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);

		if (proxyFactory.isProxyTargetClass()) {
			// Explicit handling of JDK proxy targets (for introduction advice scenarios)
			if (Proxy.isProxyClass(beanClass)) {
				// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.
				for (Class<?> ifc : beanClass.getInterfaces()) {
					proxyFactory.addInterface(ifc);
				}
			}
		}
		else {
			// No proxyTargetClass flag enforced, let's apply our default checks...
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}

		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		// Use original ClassLoader if bean class not locally loaded in overriding class loader
		ClassLoader classLoader = getProxyClassLoader();
		if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
			classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
		}
		return proxyFactory.getProxy(classLoader);
	}

在这里插入图片描述
proxyFactory 工厂拿到了目标对象和定义的切点信息 封装放到这个对象Advisor

我们细看创建代理对象的过程,发现在创建之前首先会根据切入点表达式对增强器进行一一匹配,最终拿到所有的增强器。
创建代理对象:
我们又知道spring创建代理对象有两种方式:jdk动态代理和cglib动态代理

public Object getProxy(@Nullable ClassLoader classLoader) {
		return createAopProxy().getProxy(classLoader);
	}

spring 是通过AdvisedSupport 类获取当前用户配置的方式,spring默认使用cglib动态代理

@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (!NativeDetector.inNativeImage() &&
				(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.");
			}
			//如果目标类是接口或者代理类 使用jdk代理
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

真正获取代理对象的地方cglib代理方式

org.springframework.aop.framework.CglibAopProxy#getProxy(java.lang.ClassLoader)
//根据目标对象获取一堆拦截器
//这就是给代理对象增强的核心代码
Callback[] callbacks = getCallbacks(rootClass);

Callback[] callbacks = getCallbacks(rootClass);
这个地方先混个眼熟,到调用方法时会使用这些拦截器
在这里插入图片描述

上面我们就把代理类生产了并且放到容器beanmap里面了
其中生产的过程自己断点看看吧 这个地方我们只看了一个cglib方式生产,底层使用的asm 比较复杂,这里就不再赘述.

调用方法

获取该对象看看代理对象中包含很多拦截器因此先进拦截器中
在这里插入图片描述

这个时候拦截器就起作用了直接进入下面的方法

org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor#intercept
//获取可以应用到此方法上的Interceptor列表
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
				Object retVal;
				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;

在这里插入图片描述

private static class CglibMethodInvocation extends ReflectiveMethodInvocation {
反射机制 掉用proceed 走父类的
ReflectiveMethodInvocation
通过反射就可以在执行代码的前后进行增强了
这个地方自己不是很熟悉的可以自己看看 反射和动态代理相关的知识

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-12-03 12:54:30  更:2021-12-03 12:54:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:46:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码