java spring 12 bean的初始化:initializeBean

0.例子:

@Component
public class SetterBean implements BeanNameAware, InitializingBean {

    private String beanName;

    @Resource(name = "beanService1")
    private BeanService beanService;

    @Override
    public void setBeanName(String name) {
        beanName = name;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("SetterBean run afterPropertiesSet");
    }

    @PostConstruct
    public void testPostConstruct() {
        System.out.println("SetterBean run PostConstruct");
        System.out.println("this beanName : " + beanName);
    }
}

@Configuration
public class ConfigurationBean {

    @Bean(initMethod = "initMethodTest")
    public BeanServiceInitMethod beanService1() {
        return new BeanServiceInitMethod();
    }

    @Bean
    public BeanService beanService() {
        BeanServiceImpl beanService = new BeanServiceImpl();
        beanService.setName("zhangsan");
        return beanService;
    }
}

@Component
public class BeanServiceInitMethod implements BeanService {
    private String name;

    public void initMethodTest() throws Exception {
        System.out.println("BeanServiceInitMethod run initMethodTest");
    }
}

1.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 {
		// 4.1. 调用Aware扩展接口
		invokeAwareMethods(beanName, bean);
	}

	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
		// 4.2. 引用初始化前后置处理器,@PostConstruct的方法便是此处调用的
		wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
	}

	try {
		// 4.3. 调用初始化方法,afterPropertiesSet方法便是此处调用
		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()) {
		// 4.4. 引用初始化后后置处理器
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}

	return wrappedBean;
}

2.invokeAwareMethods方法:

为了让我们的bean可以感知到容器内的一些东西,所以Spring为我们提供了Aware接口 `
这里分别是让bean能够感知到beanName、ClassLoader、BeanFactory

private void invokeAwareMethods(String beanName, Object bean) {
	if (bean instanceof Aware) {
		if (bean instanceof BeanNameAware) {
			// 实现BeanNameAware接口的类可以感知到beanName,让Bean获取自己在BeanFactory配置中的名字(根据情况是id或者name)。
			((BeanNameAware) bean).setBeanName(beanName);
		}
		if (bean instanceof BeanClassLoaderAware) {
			ClassLoader bcl = getBeanClassLoader();
			// 实现BeanClassLoaderAware接口的类可以感知到beanClassLoader
			if (bcl != null) {
				((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
			}
		}
		if (bean instanceof BeanFactoryAware) {
			// 实现BeanFactoryAware接口的类可以感知到BeanFactory   是在哪个工厂(BeanFactory的引用)
			((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
		}
	}
}

2.1
Aware 接口为 Spring 容器的核心接口,是一个具有标识作用的超级接口,实现了该接口的 bean 是具有被 Spring 容器通知的能力,通知的方式是采用回调的方式。

Aware 接口是一个空接口,实际的方法签名由各个子接口来确定,且该接口通常只会有一个接收单参数的 set 方法,该 set 方法的命名方式为 set + 去掉接口名中的 Aware 后缀,即 XxxAware 接口,则方法定义为 setXxx(),例如 BeanNameAware(setBeanName),ApplicationContextAware(setApplicationContext)。

Aware 的子接口需要提供一个 setXxx 方法,我们知道 set 是设置属性值的方法,即 Aware 类接口的 setXxx 方法其实就是设置 xxx 属性值的。 Aware 的含义是感知的、感应的,那么在 Spring 容器中是如何实现感知并设置属性值得呢?我们可以从初始化 bean 中的激活 Aware 的方法 invokeAwareMethods() 中看到一点点

2.2
BeanNameAware 接口实现类:

作用:让Bean获取自己在BeanFactory配置中的名字(根据情况是id或者name)。

public class LogginBean implements BeanNameAware {

	private String beanName = null;
	
	public void setBeanName(String beanName) {
	
	this.beanName = beanName;
	
	}

}

Bean之中一定要有个String类型变量来保存BeanName的值,这个是在编写Bean代码时有程序员手工完成的,而不是通过什么特殊的饿配置。

另一个例子:
 像本栗子SetterBean是实现了BeanNameAware,SetterBean便可以感知到beanName,像本栗子只是简单赋值。
在这里插入图片描述
3.applyBeanPostProcessorsBeforeInitialization方法:

调用所有BeanPostProcessor 的 postProcessBeforeInitialization 方法,来对bean进行初始化前处理 ·
好比常用的@PostConstruct便是此处进行调用的

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

	Object result = existingBean;
	for (BeanPostProcessor processor : getBeanPostProcessors()) {
		// 调用postProcessBeforeInitialization方法来对bean进行初始化前处理
		Object current = processor.postProcessBeforeInitialization(result, beanName);
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}

3.1 @PostConstruct

@PostConstruct是Java自带的注解,在方法上加该注解会在项目启动的时候执行该方法,也可以理解为在spring容器初始化的时候执行该方法。

Java中该注解的说明:@PostConstruct该注解被用来修饰一个非静态的void()方法。被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行。

通常我们会是在Spring框架中使用到@PostConstruct注解 该注解的方法在整个Bean初始化中的执行顺序:

Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)

4.invokeInitMethods方法:

开始执行bean的初始化方法,主要处理afterPropertiesSet和initMethod

1.如果要初始化的bean实现了InitializingBean接口,就会去调用afterPropertiesSet方法
2. 如果像xml配置init-method,或者本栗中beanService1的@Bean(initMethod =“initMethodTest”),则取执行指定自定义初始化方法

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
		throws Throwable {
	// 判断初始化的bean是不是实现了InitializingBean接口
	boolean isInitializingBean = (bean instanceof InitializingBean);
	// 实现了InitializingBean接口&&重写了afterPropertiesSet方法
	if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
		if (logger.isTraceEnabled()) {
			logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
		}
		// 这个getSecurityManager一直不知道是什么,默认都不会走这里
		if (System.getSecurityManager() != null) {
			try {
				AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
					((InitializingBean) bean).afterPropertiesSet();
					return null;
				}, getAccessControlContext());
			}
			catch (PrivilegedActionException pae) {
				throw pae.getException();
			}
		}
		// 执行bean重写的afterPropertiesSet方法
		else {
			((InitializingBean) bean).afterPropertiesSet();
		}
	}

	// 初始化的bean没有实现了InitializingBean接口,像本栗子beanService1这个bean
	if (mbd != null && bean.getClass() != NullBean.class) {
		// 获取bean的初始化方法名
		String initMethodName = mbd.getInitMethodName();
		// 存在初始化方法&&
		// (没有实现了InitializingBean接口&&初始化方法名不是afterPropertiesSet&&是外部管理的初始化方法)
		if (StringUtils.hasLength(initMethodName) &&
				!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
				!mbd.isExternallyManagedInitMethod(initMethodName)) {
			// 执行自定义的初始化方法,像本栗子的initMethodTest方法
			// 如果初始化方法名为空则默认抛异常,否则通过反射来调用自定义的初始化方法
			invokeCustomInitMethod(beanName, bean, mbd);
		}
	}
}

5.applyBeanPostProcessorsAfterInitialization方法

调用所有BeanPostProcessor 的 postProcessAfterInitialization 方法,来对bean进行初始化后处理
这里如果有AOP会进行代理对象的处理,后面再介绍
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;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值