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知识库 -> Bean的生命周期和AOP -> 正文阅读

[Java知识库]Bean的生命周期和AOP

一:从bean的生命周期四个阶段开始说起。

先附上源码:

// 忽略了无关代码
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
      throws BeanCreationException {
    
   // Instantiate the bean.
   BeanWrapper instanceWrapper = null;
   if (instanceWrapper == null) {
       // 实例化阶段!
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }

// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
	boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
	if (earlySingletonExposure) {
		if (logger.isTraceEnabled()) {
			logger.trace("Eagerly caching bean '" + beanName +
					"' to allow for resolving potential circular references");
		}
		addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
	}
    
   // Initialize the bean instance.
   Object exposedObject = bean;
   try {
       // 属性赋值阶段!
      populateBean(beanName, mbd, instanceWrapper);
       // 初始化阶段!
      exposedObject = initializeBean(beanName, exposedObject, mbd);
   }
}

第一阶段? createBeanInstance()方法实例化bean?

顺便提一下 为了解决循环依赖问题向缓存暴露bean工厂?

第二阶段??populateBean() 属性注入

第三阶段??initializeBean() 方法 进入初始化阶段

第四阶段? 销毁

二:初始化阶段到底都干了些什么?AOP发生在哪里?

先说答案:

????????初始化阶段执行Aware接口 和 后置处理器方法? 执行初始化方法

? ? ? ? AOP发生在初始化方法执行后

附上initializeBean()源码

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 {
            // 1: 执行Aware接口方法
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
            // 2: 剩余的Aware接口方法 + 后置处理器
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
            // 3: 初始化方法
			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()) {
            // 后置处理器(在这里完成AOP代理)
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

第一步?执行部分Aware接口 ?

private void invokeAwareMethods(String beanName, Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof BeanNameAware) {
				((BeanNameAware) bean).setBeanName(beanName);
			}
			if (bean instanceof BeanClassLoaderAware) {
				ClassLoader bcl = getBeanClassLoader();
				if (bcl != null) {
					((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
				}
			}
			if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}
		}
	}

实现了BeanNameAware BeanClassLoaderAware BeanFactoryAware的bean会执行 ,这三个接口分别会获得bean的name、加载器、工厂

第二步?applyBeanPostProcessorBeforeInitialization()方法?

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

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessBeforeInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

就是循环调用后置处理器的postProcessBeforeInitialization()方法。执行剩下的Aware接口 如ApplicationContextAware(可以让我们拿到整个容器),它会被一个专门的后置处理器ApplicationContextAwareProcessor处理 。以及对 @PostConstructor 和 @PreDestroy注解的处理。这两个注解会被CommonAnnotationBeanPostProcessor这个后置处理器处理
(@PostConstructor注解 : 修饰一个非静态的void方法 该方法会在服务器加载Servlet时运行 且只会被服务器执行一次)?

第三步:?invokeInitMethods() 初始化方法执行

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {
        // 是否实现了 InitializingBean接口
		boolean isInitializingBean = (bean instanceof InitializingBean);
		if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
			if (logger.isTraceEnabled()) {
				logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
			}
			if (System.getSecurityManager() != null) {
				try {
					AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {                    
                        // 调用afterPropertiesSet方法
						((InitializingBean) bean).afterPropertiesSet();
						return null;
					}, getAccessControlContext());
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
                 // 调用afterPropertiesSet方法
				((InitializingBean) bean).afterPropertiesSet();
			}
		}

		if (mbd != null && bean.getClass() != NullBean.class) {
			String initMethodName = mbd.getInitMethodName();
			if (StringUtils.hasLength(initMethodName) &&
					!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
					!mbd.isExternallyManagedInitMethod(initMethodName)) {
				invokeCustomInitMethod(beanName, bean, mbd);
			}
		}
	}

?对实现了InitialzingBean接口的Bean先调用接口中的afterPropertiesSet()方法 ?之后再判断是否在Xml的Bean标签中提供了init-method属性

第四步?applyBeanPostProcessorsAfterInitialization() 后置处理器的方法

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

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

比如完成AOP的代理 ?@EnableAspectJAutoProxy注解实际上就是向容器中注册了一个AnnotationAwareAspectJAutoProxyCreator,这个类本身就是一个后置处理器,AOP代理就是由它在这一步完成的。
?

三:和AOP相关的后置处理器具体做了什么呢?

就是执行父类AbstractAutoProxyCreator的postProcessAfterInitialization()方法

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;
	}
//省略了部分代码
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		
		// Create proxy if we have advice.
        // 获取可以应用到这个Bean上的通知
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        // 如果存在通知的话,说明需要被代理
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
            //重点在这,创建代理,实际上底层就是new了一个ProxyFactory来创建代理的
			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;
	}

? createProxy()?

//省略部分代码	

/**
	 * Create an AOP proxy for the given bean.
	 * @param beanClass the class of the bean
	 * @param beanName the name of the bean
	 * @param specificInterceptors the set of interceptors that is
	 * specific to this bean (may be empty, but not null)
	 * @param targetSource the TargetSource for the proxy,
	 * already pre-configured to access the bean
	 * @return the AOP proxy for the bean
	 * @see #buildAdvisors
	 */
	protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {

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

		return proxyFactory.getProxy(getProxyClassLoader());
	}

getProxy()

?这里有Java动态代理和Cglib代理两种不同的实现方式。我们主要看JdkDynamicAopProxy。

public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
		}
        // proxiedInterfaces是所有需要实现的接口
		return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
	}

proxiedInterfaces是JdkDynamicAopProxy 的私有属性

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
    private final Class<?>[] proxiedInterfaces;
    public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
		Assert.notNull(config, "AdvisedSupport must not be null");
		if (config.getAdvisorCount() == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
			throw new AopConfigException("No advisors and no TargetSource specified");
		}
		this.advised = config;
		this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
	}
}

通过completeProxiedInterfaces()方法获取需要实现的接口

static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
    // 第一步:获取在配置中指定的需要实现的接口
    Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();
    
    // 第二步:如果没有指定需要实现的接口,但是需要代理的目标类本身就是一个接口
    // 那么将其添加到代理类需要实现的接口的集合中
    // 如果目标类本身不是一个接口,但是是经过jdk代理后的一个类
    // 那么获取这个代理后的类所有实现的接口,并添加到需要实现的接口集合中
    if (specifiedInterfaces.length == 0) {
        Class<?> targetClass = advised.getTargetClass();
        if (targetClass != null) {
            if (targetClass.isInterface()) {
                advised.setInterfaces(targetClass);
            }
            else if (Proxy.isProxyClass(targetClass)) {
                advised.setInterfaces(targetClass.getInterfaces());
            }
            specifiedInterfaces = advised.getProxiedInterfaces();
        }
    }
    
    // 第三步:为代理类添加三个默认需要实现的接口,分别是
    // 1.SpringProxy,一个标记接口,代表这个类是通过Spring的AOP代理生成的
    // 2.Advised,提供了管理通知的方法
    // 3.DecoratingProxy,用户获取到真实的目标对象
    // 这个真实对象指的是在嵌套代理的情况下会获取到最终的目标对象
    // 而不是指返回这个ProxyFactory的target
    boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class);
    boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class);
    boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class));
    int nonUserIfcCount = 0;
    if (addSpringProxy) {
        nonUserIfcCount++;
    }
    if (addAdvised) {
        nonUserIfcCount++;
    }
    if (addDecoratingProxy) {
        nonUserIfcCount++;
    }
    Class<?>[] proxiedInterfaces = new Class<?>[specifiedInterfaces.length + nonUserIfcCount];
    System.arraycopy(specifiedInterfaces, 0, proxiedInterfaces, 0, specifiedInterfaces.length);
    int index = specifiedInterfaces.length;
    if (addSpringProxy) {
        proxiedInterfaces[index] = SpringProxy.class;
        index++;
    }
    if (addAdvised) {
        proxiedInterfaces[index] = Advised.class;
        index++;
    }
    if (addDecoratingProxy) {
        proxiedInterfaces[index] = DecoratingProxy.class;
    }
    return proxiedInterfaces;
}

invoke()?

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    Object oldProxy = null;
    boolean setProxyContext = false;

    TargetSource targetSource = this.advised.targetSource;
    Object target = null;

    try {
        // 首先处理的是hashCode跟equals方法
        // 如果接口中没有定义这两个方法,那么会调用本类中定义的equals方法
        // 前面我们也说过了,只有当两个类的目标对象,通知以及实现的接口都相等的情况下
        // equals才会返回true
        // 如果接口中定义了这两个方法,那么最终会调用目标对象中的方法
        if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
            return equals(args[0]);
        }
        else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
            return hashCode();
        }
        
        // 也就是说我们调用的是DecoratingProxy这个接口中的方法
        // 这个接口中只定义了一个getDecoratedClass方法,用于获取到
        // 最终的目标对象,在方法实现中会通过一个while循环来不断接近
        // 最终的目标对象,直到得到的目标对象不是一个被代理的对象才会返回
        else if (method.getDeclaringClass() == DecoratingProxy.class) {
            return AopProxyUtils.ultimateTargetClass(this.advised);
        }
        
        // 说明调用的是Advised接口中的方法,这里只是单纯的进行反射调用
        else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                 method.getDeclaringClass().isAssignableFrom(Advised.class)) {

            return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
        }

        Object retVal;
		
        // 说明需要将代理类暴露到线程上下文中
        // 调用AopContext.setCurrentProxy方法将其放入到一个threadLocal中
        if (this.advised.exposeProxy) {
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
        }
		
        // 接下来就是真正的执行代理逻辑了
        target = targetSource.getTarget();
        Class<?> targetClass = (target != null ? target.getClass() : null);
		
        // 先获取整个拦截器链
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
        
        // 如果没有进行拦截,直接反射调用方法
        if (chain.isEmpty()) {
            Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
            retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
        }
        
        // 否则开始执行整个链条
        else {
            MethodInvocation invocation =
                new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
            retVal = invocation.proceed();
        }
	
        // 这里是处理一种特殊情况,就是当执行的方法返回值为this的情况
        // 这种情况下,需要返回当前的代理对象而不是目标对象
        Class<?> returnType = method.getReturnType();
        if (retVal != null && retVal == target &&
            returnType != Object.class && returnType.isInstance(proxy) &&
            !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
            retVal = proxy;
        }
        else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
            throw new AopInvocationException(
                "Null return value from advice does not match primitive return type for: " + method);
        }
        return retVal;
    }
    finally {
        if (target != null && !targetSource.isStatic()) {
            targetSource.releaseTarget(target);
        }
        if (setProxyContext) {
            AopContext.setCurrentProxy(oldProxy);
        }
    }
}

核心就是?

获取整个拦截器链 然后在在拦截器链上执行方法

如果还想深入研究?

附上链接?Spring中AOP相关的API及源码解析,原来AOP是这样子的_程序员DMZ的博客-CSDN博客

? 文章参考:Spring中AOP相关的API及源码解析,原来AOP是这样子的_程序员DMZ的博客-CSDN博客Spring中AOP相关的API及源码解析本系列文章:读源码,我们可以从第一行读起你知道Spring是怎么解析配置类的吗?配置类为什么要添加@Configuration注解?谈谈Spring中的对象跟Bean,你知道Spring怎么创建对象的吗?这篇文章,我们来谈一谈Spring中的属性注入 推荐阅读:Spring官网阅读 | 总结篇Spring杂谈本系列文章将会带你一行行的将Spring的源码吃透,推荐阅读的文章是阅读源码的基础!因为本文会涉及到动态代理的相关内容,如果对动态代理不https://blog.csdn.net/qq_41907991/article/details/107089754Spring中Bean的生命周期https://www.cychee.cn/archives/spring-zhong-bean-de-sheng-ming-zhou-qiSpring中AOP相关的API及源码解析,原来AOP是这样子的_程序员DMZ的博客-CSDN博客你知道Spring是怎么将AOP应用到Bean的生命周期中的吗?_程序员DMZ的博客-CSDN博客聊一聊Spring是怎么将AOP应用到Bean的生命周期中的?本系列文章:听说你还没学Spring就被源码编译劝退了?30+张图带你玩转Spring编译读源码,我们可以从第一行读起你知道Spring是怎么解析配置类的吗?配置类为什么要添加@Configuration注解?谈谈Spring中的对象跟Bean,你知道Spring怎么创建对象的吗?这篇文章,我们来谈一谈Spring中的属性注入 Spring中AOP相关的API及源码解析,原来AOP是这样子的推荐阅读:Spring官网阅读 |https://daimingzhi.blog.csdn.net/article/details/107141101

?

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-04-04 11:57:16  更:2022-04-04 12:01:27 
 
开发: 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 7:18:53-

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