第三讲、Spring之bean生命周期
文章内容根据黑马程序员Spring视频教程所写!!!
视频地址:点击这里
Spring Bean生命周期的各个阶段
生命周期的执行顺序
/**
* @author Becant
* 2024-04-25-17:52
* @version 1.0.0
* bean生命周期
*/
@SpringBootApplication
public class A03Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(A03Application.class, args);
context.close();
}
}
@Component
public class LifeCycleBean {
private static final Logger log = LoggerFactory.getLogger(LifeCycleBean.class);
public LifeCycleBean() {
log.info("构造");
}
// 说明:@Autowired不会注入String类型的bean,如果有@Value修饰,则会以值注入的方式注入bean
@Autowired
public void autowired(@Value("${JAVA_HOME}") String home) {
log.info("依赖注入:{}", home);
}
// 注解作用:初始化
@PostConstruct
public void init() {
log.info("初始化");
}
// 注解作用:销毁
@PreDestroy
public void destroy() {
log.info("销毁");
}
}
控制台打印:
执行顺序:构造方法->依赖注入->初始化->销毁
。Spring bean只有这四个生命周期
生命周期的功能增强
生命周期功能增强也就是:生命周期某个阶段的执行前后要增加的功能
/**
* @author Becant
* 2024-04-25-18:09
* @version 1.0.0
* 后处理器
*/
//实现了两个Bean后处理器
@Component
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {
private static final Logger log = LoggerFactory.getLogger(MyBeanPostProcessor.class);
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
if (beanName.equals("LifeCycleBean")) {
log.info("<<<<<<<<<<<<<<<<销毁之前执行, 如@preDestroy");
}
}
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if (beanName.equals("LifeCycleBean")) {
log.info("<<<<<<<<实例化之前执行, 这里返回的对象会替换原本的bean,返回null则Bean不会被替换");
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if (beanName.equals("LifeCycleBean")) {
log.info("<<<<<<<<实例化之后执行, 这里返回false会跳过依赖注入阶段,返回true则不会");
// return false;
}
return true;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if (beanName.equals("LifeCycleBean")) {
log.info("<<<<<<<<依赖注入阶段执行, 扩展功能,如解析@Autowired @Resource @Value");
}
return pvs;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("LifeCycleBean")) {
log.info("<<<<<<<<初始化之前执行, 这里返回的对象会替换原本的bean,返回null则Bean不会被替换 如@PostConstruct @ConfigurationProperties");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("LifeCycleBean")) {
log.info("<<<<<<<<初始化之后执行, 这里返回的对象会替换原本的bean,返回null则Bean不会被替换 如代理增强");
}
return bean;
}
}
控制台打印:
模板方法
模版方法是设计模式的其中一种,使用模版方法能使代码更容易扩展。
现在有一个方法
public Object getBean() {
Object bean = new Object();
System.out.println("构造" + bean);
System.out.println("依赖注入" + bean);
System.out.println("初始化" + bean);
return bean;
}
如果我们想在依赖注入阶段增强功能,例如增加@Autowired和@Resource的解析。如果不是用模版方法,只能在刚方法的基础上修改代码,这样就违反了开放封闭原则,对修改封闭,对扩展开放。
public Object getBean() {
Object bean = new Object();
System.out.println("构造" + bean);
System.out.println("依赖注入" + bean);
System.out.println("解析@Autowired");
System.out.println("解析@Resource");
System.out.println("初始化" + bean);
return bean;
}
如果使用模版方法
public class TestMethodTemplate {
public static void main(String[] args) {
MyBeanFactory beanFactory = new MyBeanFactory();
// 扩展功能
beanFactory.addBeanPostProcessor(bean -> System.out.println("解析 @Autowired"));
beanFactory.addBeanPostProcessor(bean -> System.out.println("解析 @Resource"));
beanFactory.getBean();
}
static class MyBeanFactory {
public Object getBean() {
Object bean = new Object();
System.out.println("构造" + bean);
System.out.println("依赖注入" + bean);
for (BeanPostProcessor processor : processors) {
processor.inject(bean);
}
System.out.println("初始化" + bean);
return bean;
}
// 模版接口集合
private List<BeanPostProcessor> processors = new ArrayList<>();
// 增加BeanPostProcessor,扩展功能
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
processors.add(beanPostProcessor);
}
}
// 模版接口
static interface BeanPostProcessor {
public void inject(Object bean);
}
}
使用模版方法,观察getBean()方法,对于一些能确定的扩展(静态部分)保持不变;对于一些不能确定的扩展(动态部分),把它抽象成接口(或者抽象类),这个模版接口所声明的方法,是我们要自己实现的,即根据自己所需实现功能。然后在getBean()方法所在的类上添加一个管理模版接口的集合,以及add方法(把模板接口添加到集合)。在getBean()类上遍历集合,调用方法,就能实现功能。功能的扩展只需要在main函数上添加代码,而不需要修改getBean()函数。
第三讲、Spring之bean生命周期
http://example.com/2024/04/25/第三讲、Spring之bean生命周期/