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方法执行了.........");}@Overridepublic void setBeanName(String name) {log.info("setBeanName方法执行了.........");}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {log.info("BeanFactoryAware-setBeanFactory方法执行了.........");}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {log.info("ApplicationContextAware-setApplicationContext方法执行了........");}@PostConstructpublic void selfInit() {log.info("自定义init方法执行了.................");}@Overridepublic void afterPropertiesSet() throws Exception {log.info("InitializingBean-afterPropertiesSet方法执行了........");}@PreDestroypublic void selfDestory() {log.info("自定义destory方法执行了...............");}@Overridepublic 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 {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("user")) {System.out.println("postProcessBeforeInitialization方法执行了->user对象初始化方法前开始增强....");}return bean;}@Overridepublic 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() {@Overridepublic 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