Spring IOC作用域和生命周期(xml)

发布于 2021-08-25  50 次阅读


首先单例和多例的结果不一样,因为ClassPathXmlApplicationContext如果是单例的话是在一开始运行服务器的时候就建好对象,而多例则是getBean时再建;

1.MyBeanPost后置处理器

package com.apesblog.demo;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBeanPost implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization");
        return null;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization");
        return null;
    }
}

2.User类

package com.apesblog.demo;

public class User {

    String name;

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

    public User() {
        System.out.println("执行无参构造");
    }

    public void setName(String name) {
        this.name = name;
        System.out.println("执行set方法");
    }

    public void initMethod(){
        System.out.println("initMethod");
    }
    public void destroyMethod(){
        System.out.println("destroyMethod");
    }

}

3.测试类

package com.apesblog.demo.Test1;

import com.apesblog.demo.User;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test1 {
    @Test
    public void test1(){
        System.out.println("启动服务器");
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("bean1.xml");
        System.out.println("-----------");
        User user = classPathXmlApplicationContext.getBean("user", User.class);
        System.out.println(user);
        System.out.println("-----------");
        User user1 = classPathXmlApplicationContext.getBean("user", User.class);
        System.out.println(user1);
        classPathXmlApplicationContext.close();
    }
}

结果(单例xml)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="user" class="com.apesblog.demo.User" init-method="initMethod" destroy-method="destroyMethod" scope="singleton">
        <property name="name" value="apesblog"></property>
    </bean>

    <bean id="mybeanpost" class="com.apesblog.demo.MyBeanPost"></bean>
</beans>

结果(多例xml)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.apesblog.demo.User" init-method="initMethod" destroy-method="destroyMethod" scope="prototype">
    <property name="name" value="apesblog"></property>
</bean>

<bean id="mybeanpost" class="com.apesblog.demo.MyBeanPost"></bean>
</beans>

总结:

ClassPathXmlApplicationContext类会在启动服务器的时候创建好Bean,
BeanFactory会在getBean时才创建Bean,但是ClassPathXmlApplicationContext提前创建可能运行时性能上快一点。

单例模式下:

Bean是在启动服务器就创建好的,每次执行getBean返回同一个引用就行,最后再执行destroyMethod方法。

多例模式下:

Bean是在每次执行getBean才创建,但是destroyMethod方法为啥不执行,目前不清楚。

补充:

  1. 多实例的时候bean不会随着IOC容器的构建而创建,而是在使用的时候创建的getBean()
  2. 多实例的时候,当容器进行关闭的时候,bean实例不会调用destroy方法,说明容器不控制多实例的销毁
  3. 多实例的情况下,返回的bean的对象是不一样的