Bean生命周期:
-
创建 Bean 的实例:Bean 容器首先会找到配置文件中的 Bean 定义,然后使用 Java 反射 API 来创建 Bean 的实例。
-
Bean 属性赋值/填充:为 Bean 设置相关属性和依赖,例如
@Autowired
等注解注入的对象、@Value
注入的值、setter
方法或构造函数注入依赖和值、@Resource
注入的各种资源。 -
Bean 初始化:
Aware
接口能让 Bean 能拿到 Spring 容器资源。- 如果 Bean 实现了
BeanNameAware
接口,调用setBeanName()
方法,传入 Bean 的名字。 - 如果 Bean 实现了
BeanClassLoaderAware
接口,调用setBeanClassLoader()
方法,传入ClassLoader
对象的实例。 - 如果 Bean 实现了
BeanFactoryAware
接口,调用setBeanFactory()
方法,传入BeanFactory
对象的实例。 - 与上面的类似,如果实现了其他
*.Aware
接口,就调用相应的方法。 - 如果有和加载这个 Bean 的 Spring 容器相关的
BeanPostProcessor
对象,执行postProcessBeforeInitialization()
方法 - 如果 Bean 实现了
InitializingBean
接口,执行afterPropertiesSet()
方法。 - 如果 Bean 在配置文件中的定义包含
init-method
属性,执行指定的方法。或者,也可以直接通过@PostConstruct
注解标记 Bean 初始化执行的方法。 - 如果有和加载这个 Bean 的 Spring 容器相关的
BeanPostProcessor
对象,执行postProcessAfterInitialization()
方法。
- 如果 Bean 实现了
-
销毁 Bean:销毁并不是说要立马把 Bean 给销毁掉,而是把 Bean 的销毁方法先记录下来,将来需要销毁 Bean 或者销毁容器的时候,就调用这些方法去释放 Bean 所持有的资源。
- 如果 Bean 实现了
DisposableBean
接口,执行destroy()
方法。 - 如果 Bean 在配置文件中的定义包含
destroy-method
属性,执行指定的 Bean 销毁方法。或者,也可以直接通过@PreDestroy
注解标记 Bean 销毁之前执行的方法。
- 如果 Bean 实现了
Bean生命周期流程如图所示:
代码测试:
package com.spring.demo.liftcycle;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Component
@Slf4j
// public class User {
public class User implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean {
public User() {
log.info("User的构造方法执行了.........");
}
private String name;
@Value(value = "张三")
public void setName(String name) {
log.info("BeanNameAware-setName方法执行了.........");
}
@Override
public void setBeanName(String name) {
log.info("setBeanName方法执行了.........");
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
log.info("BeanFactoryAware-setBeanFactory方法执行了.........");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
log.info("ApplicationContextAware-setApplicationContext方法执行了........");
}
@PostConstruct
public void selfInit() {
log.info("自定义init方法执行了.................");
}
@Override
public void afterPropertiesSet() throws Exception {
log.info("InitializingBean-afterPropertiesSet方法执行了........");
}
@PreDestroy
public void selfDestory() {
log.info("自定义destory方法执行了...............");
}
@Override
public void destroy() throws Exception {
log.info("DisposableBean-destroy方法执行........");
}
}
package com.spring.demo.liftcycle;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.InvocationHandler;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("user")) {
System.out.println("postProcessBeforeInitialization方法执行了->user对象初始化方法前开始增强....");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("user")) {
System.out.println("postProcessAfterInitialization->user对象初始化方法后开始增强....");
//cglib代理对象
Enhancer enhancer = new Enhancer();
//设置需要增强的类
enhancer.setSuperclass(bean.getClass());
//执行回调方法,增强方法
enhancer.setCallback(new InvocationHandler() {
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
//执行目标方法
return method.invoke(method,objects);
}
});
//创建代理对象
return enhancer.create();
}
return bean;
}
}
日志输出:
2024-07-04 21:54:20.649 INFO 256748 --- [ main] com.spring.demo.liftcycle.User : User的构造方法执行了.........
2024-07-04 21:54:20.652 INFO 256748 --- [ main] com.spring.demo.liftcycle.User : BeanNameAware-setName方法执行了.........
2024-07-04 21:54:20.652 INFO 256748 --- [ main] com.spring.demo.liftcycle.User : setBeanName方法执行了.........
2024-07-04 21:54:20.652 INFO 256748 --- [ main] com.spring.demo.liftcycle.User : BeanFactoryAware-setBeanFactory方法执行了.........
2024-07-04 21:54:20.653 INFO 256748 --- [ main] com.spring.demo.liftcycle.User : ApplicationContextAware-setApplicationContext方法执行了........
postProcessBeforeInitialization方法执行了->user对象初始化方法前开始增强....
2024-07-04 21:54:20.653 INFO 256748 --- [ main] com.spring.demo.liftcycle.User : 自定义init方法执行了.................
2024-07-04 21:54:20.653 INFO 256748 --- [ main] com.spring.demo.liftcycle.User : InitializingBean-afterPropertiesSet方法执行了........
postProcessAfterInitialization->user对象初始化方法后开始增强....
2024-07-04 21:54:20.655 INFO 256748 --- [ main] com.spring.demo.liftcycle.User : User的构造方法执行了.........
2024-07-04 21:54:20.912 INFO 256748 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2024-07-04 21:54:20.918 INFO 256748 --- [ main] com.spring.demo.SpringDemoApplication : Started SpringDemoApplication in 2.011 seconds (JVM running for 2.649)
Disconnected from the target VM, address: '127.0.0.1:4158', transport: 'socket'
2024-07-04 21:54:30.871 INFO 256748 --- [ionShutdownHook] com.spring.demo.liftcycle.User : 自定义destory方法执行了...............
2024-07-04 21:54:30.872 INFO 256748 --- [ionShutdownHook] com.spring.demo.liftcycle.User : DisposableBean-destroy方法执行........
Process finished with exit code 130