千家信息网

Spring的Aware注入源码分析

发表于:2025-01-23 作者:千家信息网编辑
千家信息网最后更新 2025年01月23日,本篇内容介绍了"Spring的Aware注入源码分析"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!A
千家信息网最后更新 2025年01月23日Spring的Aware注入源码分析

本篇内容介绍了"Spring的Aware注入源码分析"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

Aware注入

在使用Spring的时候我们将自己的Bean实现BeanNameAware接口、BeanFactoryAware接口等,依赖容器帮我们注入当前Bean的名称或者Bean工厂,其代码实现的initializeBean方法:

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {

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

AccessController.doPrivileged(new PrivilegedAction() {

public Object run() {

invokeAwareMethods(beanName, bean);

return null;

}

}, getAccessControlContext());

}

else {

invokeAwareMethods(beanName, bean);

}

Object wrappedBean = bean;

if (mbd == null || !mbd.isSynthetic()) {

wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);

}

try {

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()) {

wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

}

return wrappedBean;

}

看一下上面第5行的实现:

private void invokeAwareMethods(final String beanName, final Object bean) {

if (bean instanceof BeanNameAware) {

((BeanNameAware) bean).setBeanName(beanName);

}

if (bean instanceof BeanClassLoaderAware) {

((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());

}

if (bean instanceof BeanFactoryAware) {

((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);

}

}

看到这里判断,如果bean是BeanNameAware接口的实现类会调用setBeanName方法、如果bean是BeanClassLoaderAware接口的实现类会调用setBeanClassLoader方法、如果是BeanFactoryAware接口的实现类会调用setBeanFactory方法,注入对应的属性值。

调用BeanPostProcessor的postProcessBeforeInitialization方法

上面initializeBean方法再看16行其实现:

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)

throws BeansException {

Object result = existingBean;

for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {

result = beanProcessor.postProcessBeforeInitialization(result, beanName);

if (result == null) {

return result;

}

}

return result;

}

遍历每个BeanPostProcessor接口实现,调用postProcessBeforeInitialization方法,这个接口的调用时机之后会总结,这里就代码先简单提一下。

调用初始化方法

initializeBean方法的20行,调用Bean的初始化方法,看一下实现:

protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)

throws Throwable {

boolean isInitializingBean = (bean instanceof InitializingBean);

if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {

if (logger.isDebugEnabled()) {

logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");

}

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

try {

AccessController.doPrivileged(new PrivilegedExceptionAction() {

public Object run() throws Exception {

((InitializingBean) bean).afterPropertiesSet();

return null;

}

}, getAccessControlContext());

}

catch (PrivilegedActionException pae) {

throw pae.getException();

}

}

else {

((InitializingBean) bean).afterPropertiesSet();

}

}

if (mbd != null) {

String initMethodName = mbd.getInitMethodName();

if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&

!mbd.isExternallyManagedInitMethod(initMethodName)) {

invokeCustomInitMethod(beanName, bean, mbd);

}

}

}

看到,代码做了两件事情:

1、先判断Bean是否InitializingBean的实现类,是的话,将Bean强转为InitializingBean,直接调用afterPropertiesSet()方法

2、尝试去拿init-method,假如有的话,通过反射,调用initMethod

因此,两种方法各有优劣:使用实现InitializingBean接口的方式效率更高一点,因为init-method方法是通过反射进行调用的;从另外一个角度讲,使用init-method方法之后和Spring的耦合度会更低一点。具体使用哪种方式调用初始化方法,看个人喜好。

调用BeanPostProcessor的postProcessAfterInitialization方法

最后一步,initializeBean方法的29行:

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;

}

同样遍历BeanPostProcessor,调用postProcessAfterInitialization方法。因此对于BeanPostProcessor方法总结一下:

1、在初始化每一个Bean的时候都会调用每一个配置的BeanPostProcessor的方法

2、在Bean属性设置、Aware设置后调用postProcessBeforeInitialization方法

3、在初始化方法调用后调用postProcessAfterInitialization方法

注册需要执行销毁方法的Bean

接下来看一下最上面doCreateBean方法的第83行registerDisposableBeanIfNecessary(beanName, bean, mbd)这一句,完成了创建Bean的最后一件事情:注册需要执行销毁方法的Bean。

看一下方法的实现:

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {

AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);

if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {

if (mbd.isSingleton()) {

// Register a DisposableBean implementation that performs all destruction

// work for the given bean: DestructionAwareBeanPostProcessors,

// DisposableBean interface, custom destroy method.

registerDisposableBean(beanName,

new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));

}

else {

// A bean with a custom scope...

Scope scope = this.scopes.get(mbd.getScope());

if (scope == null) {

throw new IllegalStateException("No Scope registered for scope '" + mbd.getScope() + "'");

}

scope.registerDestructionCallback(beanName,

new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));

}

}

}

其中第3行第一个判断为必须不是prototype(原型)的,第二个判断requiresDestruction方法的实现为:

protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {

return (bean != null &&

(bean instanceof DisposableBean || mbd.getDestroyMethodName() != null ||

hasDestructionAwareBeanPostProcessors()));

}

要注册销毁方法,Bean需要至少满足以下三个条件之一:

(1)Bean是DisposableBean的实现类,此时执行DisposableBean的接口方法destroy()

(2)Bean标签中有配置destroy-method属性,此时执行destroy-method配置指定的方法

(3)当前Bean对应的BeanFactory中持有DestructionAwareBeanPostProcessor接口的实现类,此时执行DestructionAwareBeanPostProcessor的接口方法postProcessBeforeDestruction

在满足上面三个条件之一的情况下,容器便会注册销毁该Bean,注册Bean的方法很简单,见registerDisposableBean方法实现:

public void registerDisposableBean(String beanName, DisposableBean bean) {

synchronized (this.disposableBeans) {

this.disposableBeans.put(beanName, bean);

}

}

容器销毁的时候,会遍历disposableBeans,逐一执行销毁方法。

"Spring的Aware注入源码分析"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

方法 接口 代码 容器 属性 时候 配置 源码 分析 三个 事情 内容 情况 方式 更多 条件 知识 反射 实用 学有所成 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 建设银行主机服务器在哪 网络技术获证条件 湛江无限软件开发优化价格 高中信息网络技术应用操作题 张湾区正规软件开发包括哪些 经开区配件管理软件开发 伯恩光学软件开发储备干部 数字化高校网络安全设计 崇明区音频led大屏服务器 数据库前端框架java 网络安全工程师如何入门 手机应用后台服务器泄密 网络安全专题培训ppt 域服务器功能 阜新直销软件开发制作 安全生产风险数据库 哈尔滨市网络安全有线公司 网络安全警察聊天记录恢复 h3c服务器的安全面板是什么 医学院网络技术与信息安全 怎么算把数据库学好了 江西网络营销软件开发定制排行榜 珠海市网络安全实战特训营 京东软件开发加班多吗 网络技术被应用于印刷文件的传输 网络安全专业普招专生本大学 斗地主是什么软件开发的 新服务器怎么加d盘 中国生物文献数据库简称 sql2008链接服务器
0