来源:blog.csdn.net/CYK_byte/article/details/128936138
Bean的生命周期概括图解代码示例初始化代码初始化的前置方法和后置方法(重写)Spring启动类执行结果经典面试问题总结1Bean的生命周期1.1、概括Spring中Bean的生命周期就是Bean在Spring中从创建到销毁的整个过程,主要分为以下5个部分:
1.实例化: 给Bean分配内存空间(对应JVM中的“加载”,这里只是分配了内存);
2.设置属性: 进行Bean的注入和装配;
3.初始化:
执行各种通知;执行初始化的前置工作;进行初始化工作(使用注解 @PostConstruct 初始化 或者 使用(xml)init-method 初始化, 前者技术比后者技术先进~);执行初始化的后置工作;4.使用Bean
5.销毁Bean
值得注意的是:实例化和初始化是两个完全不同的过程,前者只是给Bean分配内存空间,而后者则是将程序执行权从系统级别转到用户级别,执行用户添加的业务代码。
1.2、图解下图以买房、盖房、入住、卖房为栗子,方便理解~
图片
2代码示例2.1、初始化代码以下,我将在Spring中,演示Bean的生命周期:
创建一个类,名为BeanLifeComponent(这个名字是自定义的), 写下初始化的各类操作:
import org.springframework.beans.factory.BeanNameAware;import org.springframework.stereotype.Component; import javax.annotation.PostConstruct;import javax.annotation.PreDestroy; @Componentpublic BeanLifeComponent implements BeanNameAware { //执行各种通知 @Override public void setBeanName(String s) { System.out.println("执行了通知"); } //初始化的前置和后置方法不能写在这个Bean中! //执行初始化方法(注解) @PostConstruct public void postConstruct() { System.out.println("通过注解 @PostConstruct 执行了初始化方法"); } //使用 public void useBean() { System.out.println("使用Bean"); } //销毁 @PreDestroy public void preDestory() { System.out.println("执行了销毁方法"); } }注意:
1.这里不能写出实例化过程,因为给Bean分配内存对应JVM类加载过程;
2.当前这个Bean中不能写初始化的前置方法和后置方法,否则不会执行,因为初始化的前置方法和后置方法是需要继承BeanPostProcessor接口,重写两个方法实现的, 并且是为所有 Bean 服务的,而非为某一个 Bean 服务的,若写在一个某一个Bean中,则不会执行。
2.2、初始化的前置方法和后置方法(重写)另外再创建一个类(避免在一个Bean中),自定义名为 MyBeanPostProcessor ,接着继承BeanPostProcessor接口,重写初始化的前置方法和后置方法,如下代码:
import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanPostProcessor;import org.springframework.stereotype.Component; @Componentpublic MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("执行了初始化的前置方法"); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("执行了初始化的后置方法"); return bean; }}2.3、Spring启动类最后在Spring启动类中获取Bean对象,如下代码:
import com.demo3.component.BeanLifeComponent;import org.springframework.context.support.ClassPathXmlApplicationContext; public App3 { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml"); //获取Bean BeanLifeComponent beanLifeComponent = context.getBean("beanLifeComponent", BeanLifeComponent.class); //使用Bean beanLifeComponent.useBean(); //销毁Bean context.destroy(); }}为什么这里不使用 ApplicationContext 而是使用它的子类 ClassPathXmlApplicationContext 呢?因为 ClassPathXmlApplicationContext 中有destroy销毁方法(用来销毁容器,容器销毁了,Bean自然就没了),而ApplicationContext 中没有这个销毁方法,演示的时候,就体现不出来了。
2.4、执行结果图片
从执行结果来看,符合咱们预期~
2.5、经典面试问题那么是否可以先执行 初始化 再执行 设置属性 呢?不可以!想象一下,如果在初始化的方法中要用你设置的属性,就会引发空指针异常,如下代码:
@Controllerpublic StudentController { //属性注入 @Autowired private Student student; //初始化 @PostConstruct public void init() { student.setName("周杰伦"); } }如果你先执行了初始化 init() 方法,而 init() 方法中需要使用属性注入后得到的Student对象,那么此时还没有注入就进行修改,就会引发空指针异常。
3总结Spring中Bean的生命周期就是Bean在Spring中从创建到销毁的整个过程。
主要就是由:
实例化设置属性:进行Bean的注入和装配初始化使用Bean销毁Bean这五步构成,并且任何顺序都不可以随意调换。
Bean的执行流程属于常见面试题,一定要在理解的基础上牢记!
考框架考的就是个皮,应该最终是考底层知识