本文主要叙述的两个点:
- 如何向Spring中注册一个Bean
- Spring中Bean从创建到销毁都会经历什么(Spring Bean 的生命周期)
第一点:如何向Spring中注册一个Bean
注册一个Bean流程:
以Sentinel的为RestTemplate添加拦截器中的注册Bean为例:
完整代码:
private void registerBean(String interceptorBeanName,
SentinelRestTemplate sentinelRestTemplate, RestTemplate restTemplate) {
// register SentinelProtectInterceptor bean
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext
.getAutowireCapableBeanFactory();
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder
.genericBeanDefinition(SentinelProtectInterceptor.class);
beanDefinitionBuilder.addConstructorArgValue(sentinelRestTemplate);
beanDefinitionBuilder.addConstructorArgValue(restTemplate);
BeanDefinition interceptorBeanDefinition = beanDefinitionBuilder
.getRawBeanDefinition();
beanFactory.registerBeanDefinition(interceptorBeanName,
interceptorBeanDefinition);
}
1.获得Bean工厂
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext
.getAutowireCapableBeanFactory();
2.获得动态bean的构造器
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder
.genericBeanDefinition(SentinelProtectInterceptor.class);
3.往SentinelProtectInterceptor的构造器塞入参数并返回定义的对象
beanDefinitionBuilder.addConstructorArgValue(sentinelRestTemplate);
beanDefinitionBuilder.addConstructorArgValue(restTemplate);
BeanDefinition interceptorBeanDefinition = beanDefinitionBuilder
.getRawBeanDefinition();
public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor {
private final SentinelRestTemplate sentinelRestTemplate;
private final RestTemplate restTemplate;
public SentinelProtectInterceptor(SentinelRestTemplate sentinelRestTemplate,
RestTemplate restTemplate) {
this.sentinelRestTemplate = sentinelRestTemplate;
this.restTemplate = restTemplate;
}
// methods
}
4.注册
beanFactory.registerBeanDefinition(interceptorBeanName,
interceptorBeanDefinition);
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
由第一点引出第二点:Spring中Bean从创建到销毁都会经历什么(Spring Bean 的生命周期)
首先先看代码,然后对代码进行逐一讲解
代码地址
项目启动类
package com.narcos.frameworklearn;
import com.narcos.frameworklearn.bean.BeanOne;
import com.narcos.frameworklearn.bean.BeanTwo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
/**
* SpringBootApplication 包含了 @ComponentScan
* ComponentScan 只能扫描 FrameworkLearnApplication 所在当前包一下的 如果不在当前包 需要另外指定包的路径
*
* @author hbj
*/
@Slf4j
@SpringBootApplication
public class FrameworkLearnApplication {
public static void main(String[] args) {
ApplicationContext applicationContext = SpringApplication.run(FrameworkLearnApplication.class, args);
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
// 注册BeanOne
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(BeanOne.class);
// BeanOne构造器需要的参数
beanDefinitionBuilder.addConstructorArgValue("I am BeanOne");
// 设置init方法(BeanOne中的方法)
beanDefinitionBuilder.setInitMethodName("init");
// 设置destory方法(BeanOne中的方法)
beanDefinitionBuilder.setDestroyMethodName("destroy");
BeanDefinition interceptorBeanDefinition = beanDefinitionBuilder
.getRawBeanDefinition();
// 以beanOne为名称注册Bean
beanFactory.registerBeanDefinition("beanOne",
interceptorBeanDefinition);
// 获取BeanOne
BeanOne beanOne = (BeanOne) applicationContext.getBean("beanOne");
// 执行BeanOne的方法
log.info(beanOne.getWords());
// 销毁BeanOne
beanOne.destroy();
BeanDefinitionBuilder beanDefinitionBuilder2 = BeanDefinitionBuilder.genericBeanDefinition(BeanTwo.class);
beanDefinitionBuilder2.addConstructorArgValue("I am BeanTwo");
beanDefinitionBuilder2.setInitMethodName("init");
beanDefinitionBuilder2.setDestroyMethodName("destroy");
BeanDefinition interceptorBeanDefinition2 = beanDefinitionBuilder2
.getRawBeanDefinition();
beanFactory.registerBeanDefinition("beanTwo",
interceptorBeanDefinition2);
BeanTwo beanTwo = (BeanTwo) applicationContext.getBean("beanTwo");
log.info(beanTwo.getWords());
beanTwo.destroy();
}
}
对应的两个Bean实体
package com.narcos.frameworklearn.bean;
import lombok.extern.slf4j.Slf4j;
/**
* @author hbj
* @date 2019/10/21 23:18
*/
@Slf4j
public class BeanOne {
private String words;
public BeanOne(String words) {
this.words = words;
}
public String getWords() {
return "say : " + words;
}
public void setWords(String words) {
this.words = words;
}
public void init() {
log.info("准备初始化BeanOne");
}
public void destroy() {
log.info("准备销毁BeanOne");
}
}
package com.narcos.frameworklearn.bean;
import lombok.extern.slf4j.Slf4j;
/**
* @author hbj
* @date 2019/10/21 23:18
*/
@Slf4j
public class BeanTwo {
private String words;
public BeanTwo(String words) {
this.words = words;
}
public String getWords() {
return "say : " + words;
}
public void setWords(String words) {
this.words = words;
}
public void init() {
log.info("准备初始化BeanTwo");
}
public void destroy() {
log.info("准备销毁BeanTwo");
}
}
Bean初始化前后的处理器:
package com.narcos.frameworklearn.processor;
import com.narcos.frameworklearn.bean.BeanOne;
import com.narcos.frameworklearn.bean.BeanTwo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
/**
* 注:对所有的Bean都是有效的
*
* @author hbj
* @date 2019/10/21 23:15
*/
@Slf4j
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof BeanOne || bean instanceof BeanTwo) {
log.info("这是在Bean:{}-{}初始化前执行的前置处理器", bean, beanName);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof BeanOne || bean instanceof BeanTwo) {
log.info("这是在Bean:{}-{}初始化后执行的后置处理器", bean, beanName);
}
return bean;
}
}
执行代码,观察打印的日志
2019-10-22 10:44:43.622 INFO 9960 --- [ main] c.n.f.processor.MyBeanPostProcessor : 这是在Bean:com.narcos.frameworklearn.bean.BeanOne@280099a0-beanOne初始化前执行的前置处理器
2019-10-22 10:44:43.622 INFO 9960 --- [ main] com.narcos.frameworklearn.bean.BeanOne : 准备初始化BeanOne
2019-10-22 10:44:43.623 INFO 9960 --- [ main] c.n.f.processor.MyBeanPostProcessor : 这是在Bean:com.narcos.frameworklearn.bean.BeanOne@280099a0-beanOne初始化后执行的后置处理器
2019-10-22 10:44:43.623 INFO 9960 --- [ main] c.n.f.FrameworkLearnApplication : say : I am BeanOne
2019-10-22 10:44:43.623 INFO 9960 --- [ main] com.narcos.frameworklearn.bean.BeanOne : 准备销毁BeanOne
2019-10-22 10:44:43.623 INFO 9960 --- [ main] c.n.f.processor.MyBeanPostProcessor : 这是在Bean:com.narcos.frameworklearn.bean.BeanTwo@1bf52f10-beanTwo初始化前执行的前置处理器
2019-10-22 10:44:43.623 INFO 9960 --- [ main] com.narcos.frameworklearn.bean.BeanTwo : 准备初始化BeanTwo
2019-10-22 10:44:43.623 INFO 9960 --- [ main] c.n.f.processor.MyBeanPostProcessor : 这是在Bean:com.narcos.frameworklearn.bean.BeanTwo@1bf52f10-beanTwo初始化后执行的后置处理器
2019-10-22 10:44:43.623 INFO 9960 --- [ main] c.n.f.FrameworkLearnApplication : say : I am BeanTwo
2019-10-22 10:44:43.623 INFO 9960 --- [ main] com.narcos.frameworklearn.bean.BeanTwo : 准备销毁BeanTwo
由此我们可以发现,实例化一个Bean的流程为:
设置对象属性->BeanPostProcessor前置处理->执行自定义的initMetod->BeanPostProcessor后置处理->执行自定义的destroy方法