别找了,回答Spring中Bean的生命周期,这里帮你总结好了!

这一节准备给大家讲解Spring 容器中的Bean的生命周期。这一节我个人觉得还是比较实用的,在实际工作当中经常会用到这些知识来解决一些非常棘手的问题。

ApplicationContext中Bean的生命周期

先来张图:

å¾ç

 

大家看到这张图肯定是一脸蒙蔽。不要着急,我来慢慢解释:从getBean(…)为触发点,Spring容器的Bean生命周期就经历了图中的生命周期,先分个类:

  • 图中绿色箭头的三个步骤(InstantiationAwareBeanPostProcessor)和粉红色箭头的两个步骤(BeanPostProcessor)为容器级的生命周期接口,当Spring每加载任何一个Bean到容器中时,这些接口都会起到如图中的几次调用。这两个处理器叫做"容器级后处理器",他们的影响是全局的,能够影响所有的Bean.

  • 图中大红色圆圈圈住的接口叫做"工厂级后处理器",类似的接口还有CustomEditorConfigurer,PropertyPlaceholderConfigurer等,这类接口只在上下文初始化的时候调用一次,其目的是完成一些配置文件的加工处理工作。

  • 剩下的就简单了,属于Bean级别的接口,专属于某个Bean所有,每个Bean实例化的时候调用自己特有的。

值得一提的是,无论是"容器级后处理器"还是"工厂级后处理器",他们都是可以配置多个的(如,配置两个BeanPostProcessor),如果想控制他们的调用顺序,实现一个org.springframework.core.Ordered接口即可。当然了,一般不用,一般一类后处理器只有一个即可。

重点强调!:

这些接口的调用顺序并不是一尘不变的,会随便Spring的版本变动而变动,大家要做的是万变不离其宗,知道能够通过这些接口在Bean初始化的时做一些属性上的操作。调用顺序要根据具体的版本来自己测试。下面我会给大家来列一个例子:

public class Student implements BeanFactoryAware, BeanNameAware,
        InitializingBean, DisposableBean,ApplicationContextAware {
    private String name;

    public Student(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("BeanFactoryAware......");
    }

    @Override
    public void setBeanName(String s) {
        System.out.println("BeanNameAware......");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean......");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean......");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("ApplicationContextAware......");
    }
}

BeanFactoryPostProcessor:

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    public MyBeanFactoryPostProcessor() {
        super();
        System.out.println("这是BeanFactoryPostProcessor实现类构造器!!");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)
            throws BeansException {
        System.out.println("BeanFactoryPostProcessor调用postProcessBeanFactory方法");
        BeanDefinition bd = arg0.getBeanDefinition("student");
        MutablePropertyValues propertyValues = bd.getPropertyValues();
        //配置文件中的信息在加载到Spring中后以BeanDefinition的形式存在.在这里又可以更改BeanDefinition,所以可以理解为更改配置文件里面的内容
//        propertyValues.add("zdy","123");
    }

BeanPostProcessor:

public class MyBeanPostProcessor implements BeanPostProcessor {

    public MyBeanPostProcessor() {
        super();
        System.out.println("这是BeanPostProcessor实现类构造器!!");
    }

    @Override
    public Object postProcessAfterInitialization(Object arg0, String arg1)
            throws BeansException {
        System.out.println("BeanPostProcessor接口方法After对属性进行更改!");
        return arg0;
    }

    @Override
    public Object postProcessBeforeInitialization(Object arg0, String arg1)
            throws BeansException {
        System.out.println("BeanPostProcessor接口方法Before对属性进行更改!");
        return arg0;
    }
}

InstantiationAwareBeanPostProcessorAdapter:

public class MyInstantiationAwareBeanPostProcessor extends
        InstantiationAwareBeanPostProcessorAdapter {

    public MyInstantiationAwareBeanPostProcessor() {
        super();
        System.out.println("这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!");
    }

    // 接口方法、实例化Bean之前调用
    @Override
    public Object postProcessBeforeInstantiation(Class beanClass,
                                                 String beanName) throws BeansException {
        System.out.println("InstantiationAwareBeanPostProcessor调用Before方法");
        return null;
    }

    // 接口方法、实例化Bean之后调用
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println("InstantiationAwareBeanPostProcessor调用Ater方法");
        return bean;
    }

    // 接口方法、设置某个属性时调用
    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs,
                                                    PropertyDescriptor[] pds, Object bean, String beanName)
            throws BeansException {
        System.out.println("InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法");
        return pvs;
    }

然后我们的Main方法:

public class App 
{
    public static void main( String[] args )
    {

        ApplicationContext ac =new ClassPathXmlApplicationContext("applicationContext.xml");
        Student stu = (Student) ac.getBean("student");
        stu.setName("wangwu");
    }

Spring文件最简单:(注意要把我们自己定义的处理器全部加到容器里去)

<?xml version="1.0" encoding="UTF-8"?>
<beans
    <bean id="student" class="com.zdy.Student">
        <constructor-arg value="zhangsan"/>
    </bean>
    <bean id="myBeanFactoryPostProcessor" class="com.zdy.MyBeanFactoryPostProcessor"></bean>
    <bean id="myInstantiationAwareBeanPostProcessor" class="com.zdy.MyInstantiationAwareBeanPostProcessor"></bean>
    <bean id="myBeanPostProcessor" class="com.zdy.MyBeanPostProcessor"></bean>
</beans>

然后run一下子,看结果:

这是BeanFactoryPostProcessor实现类构造器!!
BeanFactoryPostProcessor调用postProcessBeanFactory方法
这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!
这是BeanPostProcessor实现类构造器!!
InstantiationAwareBeanPostProcessor调用Before方法
InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法
BeanNameAware......
BeanFactoryAware......
ApplicationContextAware......
BeanPostProcessor接口方法Before对属性进行更改!
InitializingBean......
InstantiationAwareBeanPostProcessor调用Ater方法
BeanPostProcessor接口方法After对属性进行更改!

好了,其实大致流程就说完了,我大致针对Bean的生命周期说一下:Spring为了尽可能的把自己内部的东西机制暴露出来给用户使用,所以在Bean创建的过程中加了很多机制,通过所谓的"处理器"Processor暴露出来,然后处理器都有自己的顺序,我们需要做的就是定义好处理器的逻辑,然后注册到Sprinhg容器中,Spring就会调用了。

其次,还有一种方式,就是让我们的Bean实现一些接口(类似于ApplicationContextAware),通过这种方式,在Bean初始化的某个步骤调用接口定义好的方法来传入一些信息进来,像ApplicationContextAware就把ApplicationContext给传给我们了。

然后我给大家说几个实用点的知识点,大家记着,用到时回来翻一翻就可以了:

  1. 上面的生命周期流程图,时候的时候注意调用先后顺序,避免属性被覆盖的现象。

  2. BeanFactoryPostProcessor 主要是在Spring刚加载完配置文件,还没来得及初始化Bean的时候做一些操作。比如篡改某个Bean在配置文件中配置的内容。

  3. InstantiationAwareBeanPostProcessorAdapter 基本没什么鸟用,Bean初始化后,还没有设置属性值时调用,和BeanFactoryPostProcessor一样,可以篡改配置文件加载到内存中的信息。

  4. ApplicationContextAware:用处很大,注入了ApplicationContext到Bean中。

  5. InitializingBean:有用处,可以在Bean属性全部改完之后,再做一些定制化操作。

  6. BeanPostProcessor:没什么用,Spring框架内部使用的比较猛,像什么AOP,动态代理,都是在这搞事。后期有时间和大家分析。

  7. 其他的像什么init-method,destroy方法,基本都是个摆设。。我是没怎么用过,只知道有这么回事。

结语

好了,Bean的生命周期算上和大家分享完了,其实没什么东西,大家知道有这么回事,能用到"后处理器"搞事的时候回来大致看下顺序即可。其次就是一些Bean实现的接口,最常用的就是(ApplicationContextAware和InitializingBean)了。还有就是BeanPostProcessor,因为这个接口的方法里会把Bean实体以Object传进去。

所以可以进行一些属性上的操作。其实说实在的,程序员用的比较少。框架内部用的多。OK,这篇讲的其实比较糙,主要是因为没什么东西可讲,Over,Have a good day !

 

这些年做Java开发我整理了一份完整的java的系统化资料,从Javase- ssm-springcloud,包括了面试题,PDF电子书等等,以及我自身之前的一个面试文案和知识点补充,如果你需要一本全面的Java书,如果你想学习Java,如果你想找到一份好的工作,那么缘分就来了,有需要的朋友可以加我的QQ学习交流裙  735721532 ,这里也祝愿大家最终都能够学有所成,早日找到满意的工作!

<think>好的,我现在需要回答用户关于SpringBean的问题。用户是Java初学者,之前询问过一段代码的语法问题,现在转向Spring框架中的概念。首先,我应该确保解释清晰,符合初学者的理解水平。 首先,用户问的是“beanSpring中是什么意思”。我需要从基础开始,解释Bean的定义,可能还要说明它在Spring中的作用。记得用户之前接触过UserDao和事务管理的代码,可以结合之前的例子来举例。 接下来,我需要考虑用户可能的困惑点。比如,Bean和普通Java对象有什么区别?Bean是如何被创建和管理的?可能还需要提到Spring容器,如ApplicationContext,因为Bean是由容器管理的。 另外,用户可能对配置方式不太了解,所以需要简要提到XML配置和注解配置,比如@Component、@Service等。同时,依赖注入也是一个关键点,用户之前的问题中提到了new对象,可以对比说明为什么使用Spring的依赖注入更好。 还要注意术语的解释,比如控制反转(IoC)和依赖注入(DI),这些概念对于理解Bean的管理机制很重要。但不要深入太多,保持基础即可。 可能用户还会想知道Bean生命周期,比如初始化、销毁方法,但作为初步介绍,可能需要简化这部分内容,或者提到有这些概念,但详细内容后续学习。 需要检查是否有常见的误解,比如Bean默认是单例的,但也可以配置其他作用域,比如prototype。用户可能在使用时遇到多个实例的问题,所以可以提到作用域的概念。 另外,结合用户之前的代码示例,比如在之前的代码中直接new了一个UserDaoImpl,而在Spring中通常会通过@Autowired注入,这样可以解耦,方便测试和管理。 最后,总结一下BeanSpring中的重要性,强调它是框架管理的组件,通过配置或注解定义,由容器负责创建和注入依赖。这样用户能有一个全面的初步认识。 需要注意避免使用过于专业的术语,或者在使用时给出简单明了的解释。保持语言口语化,结构清晰,分点说明,可能使用比喻助理解,比如将Spring容器比作工厂,负责生产和管理Bean。</think>以下是关于SpringBean的详细解释,特别结合你之前学习的代码示例进行说明: --- ### 一、Bean的本质 ```java // 你之前代码中的对象创建方式(传统方式) UserDao userDao = new UserDaoImpl(); // Spring中的Bean使用方式 @Autowired private UserDao userDao; // 由Spring容器注入 ``` - **Bean** = 被Spring容器管理的Java对象(就像工厂统一生产的零件) - **对比**:传统方式自己`new`对象 vs Spring你创建并管理对象 --- ### 二、Bean的核心特征 #### 1. 生命周期托管 ```mermaid graph LR A[定义Bean] --> B[实例化] B --> C[属性注入] C --> D[初始化方法] D --> E[使用期] E --> F[销毁方法] ``` - Spring容器控制对象的整个生命周期(程序员无需手动管理) #### 2. 依赖注入(DI) ```java // 传统代码(紧耦合) public class UserService { private UserDao userDao = new UserDaoImpl(); // 直接依赖具体实现 } // Spring方式(松耦合) public class UserService { @Autowired // 容器自动注入 private UserDao userDao; // 依赖接口 } ``` - 通过`@Autowired`自动装配对象间的依赖关系 --- ### 三、Bean的配置方式(结合你之前的代码) #### 1. XML配置(早期方式) ```xml <!-- 类似你代码中的DAO定义 --> <bean id="userDao" class="com.dao.UserDaoImpl"/> <bean id="userService" class="com.service.UserService"> <property name="userDao" ref="userDao"/> </bean> ``` #### 2. 注解配置(现代主流方式) ```java // 在你的代码基础上改造 @Repository // 标记为Bean(DAO层) public class UserDaoImpl implements UserDao { // 实现方法... } @Service // 标记为Bean(Service层) public class UserService { @Autowired // 自动注入 private UserDao userDao; } ``` --- ### 四、Bean的作用域(解决对象复用问题) | 作用域 | 描述 | 类比场景 | |---------------|------------------------------|--------------------------| | singleton | 默认,单实例(容器共用一个) | 公司唯一的打印机 | | prototype | 每次获取新实例 | 一次性纸杯 | | request | 每个HTTP请求新实例 | 快递包裹单 | | session | 每个用户会话新实例 | 用户购物车 | --- ### 五、代码对比理解 #### 原始代码(未使用Spring) ```java public void updateUserInfo(User user) { UserDao userDao = new UserDaoImpl(); // 自己管理对象 userDao.update(user); } ``` #### Spring优化后代码 ```java @Service public class UserService { @Autowired private UserDao userDao; // 由Spring注入 @Transactional // 声明式事务管理 public void updateUserInfo(User user) { userDao.update(user); } } ``` **优化点**: 1. 对象创建交给Spring 2. 通过注解实现事务管理 3. 松耦合(依赖接口而非具体实现类) --- ### 六、常见误区答疑 **问**:Bean和普通Java对象有什么区别? **答**: - 普通对象:自己`new`出来的,需要手动管理依赖 - Bean对象:由Spring容器创建,自动处理依赖注入,支持AOP等高级特性 **问**:为什么我之前代码中不用Bean也能运行? **答**: - 小项目手动管理对象可行 - 当项目规模变大时,SpringBean管理能显著提升代码可维护性和扩展性 --- **下一步学习建议**: 1. 在IDE中创建Spring Boot项目体验Bean的创建过程 2. 尝试使用`@Component`, `@Service`, `@Repository`等注解 3. 练习通过`@Autowired`实现依赖注入
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值