Spring5总述(四)—— IOC操作Bean管理(FactoryBean,Bean的作用域,Bean的生命周期,Xml的自动装配)

了解更多关于Spring的基础知识

1、FactoryBean(工厂Bean)

Spring中有两种类型的bean,一种是普通Bean,另一种是工厂Bean

  1. 普通Bean:在配置文件中定义的bean类型就是返回类型
  2. 工厂Bean:在配置文件中定义bean类型可以与返回类型不一样

1、普通Bean

Service service = context.getBean("service", Service.class);

xml文件中class属性中最后的类名Service就是返回类型,这就是一个普通bean

    <bean id="service" class="Test_bean.Service">
        <property name="list" ref="list"></property>
    </bean>

2、工厂Bean

  1. 第一步 创建类,让这个类作为工厂Bean,实现接口FactoryBean,并重写其中的方法
  1. getObject( ):该方法返回的是Mybean“生产”的对象
  2. getObjectType( ):该方法返回getObject( )方法所返回的对象的类型
  3. isSingleton( ):该方法返回的是getObject( )“生产”的对象是不是单例,如果是则返回true,不是则返回false
public class MyBean implements FactoryBean {

	//在这里我定义了它生产的对象是String类型
    @Override
    public String getObject() throws Exception {
        return "service";
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}
  1. 通过Spring配置文件配置属性
    <bean id="mybean" class="FactoryBean.MyBean"></bean>
  1. 创建测试类,进行测试
public class Springtest {

    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        String string = context.getBean("mybean", String.class);
        System.out.println(string);
    }
}
  1. 测试结果
service

2、Bean的作用域

bean具有五大作用域,在bean配置标签中,利用scope属性来设置其作用域。

  1. singleton:在Spring IOC容器中仅存在一个Bean实例,Bean以单例方式存在,如果不设置其作用域,此作用域为默认值
  2. prototype:每次从容器中调用Bean时,都会返回一个新的实例,即每次调用getBean( )时,相当于执行一次new对象的过程。
  3. request:每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext
  4. session:同一个HTTP Session共享一个Bean,不同Session使用不同Bean,仅适用于WebApplicationContext环境
  5. globalSession:一般用于Portlet应用环境,该作用域仅适用于WebApplocationContext环境

五种作用域,request、session和globalSession只在web应用中使用,因此在此我只对singleton和prototype做出解释。


1、singleton属性值:单实例(代码解释)

  1. 创建Service类
public class Service {

}
  1. Spring配置文件中,设置scope属性值为singleton
<bean id="mybean" class="Test_bean.Service" scope="singleton"></bean>
  1. 创建测试类,测试代码
public class Springtest {

    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        Service service = context.getBean("mybean", Service.class);
        Service service1 =context.getBean("mybean",Service.class);
        System.out.println(service);
        System.out.println(service1);
    }
}
  1. 测试结果
//同一实例,地址相同
Test_bean.Service@1189dd52
Test_bean.Service@1189dd52

2、prototype属性值:多实例(代码解释)

  1. 创建Service类(同上)
  2. Spring配置文件中,设置scope属性值为prototype
 <bean id="mybean" class="Test_bean.Service" scope="prototype"></bean>
  1. 创建测试类,进行测试(同上)
  2. 测试结果
Test_bean.Service@2d7275fc
Test_bean.Service@399f45b1

3、Bean的生命周期

概念:从对象创建到对象销毁的过程

3.1、bean生命周期(没有bean的后置处理器)

  1. 通过构造器创建bean实例(无参数构造)
  2. 为bean的属性设置值和对其他bean引用(调用set方法)
  3. 调用bean的初始化的方法(需要进行配置初始化的方法)
  4. bean可以使用了(对象获取到了)
  5. 当容器关闭时候,调用bean的销毁的方法(需要进行配置销毁的方法)

说明:在配置bean.xml文件时,通过init-method和destroy-method属性为bean指定初始化和销毁的方法


代码演示:

  1. 创建Service类,创建初始化,set,init-method,destroy-method方法
public class Service {
    private String name;
    
    public Service(){
        System.out.println("第一步:执行无参数构造方法创建bean实例");
    }

    public void setName(String name) {
        this.name = name;
        System.out.println("第二步:调用setter方法为属性赋值");
    }
    
    public void initMethod(){
        System.out.println("第三步:执行init-method初始化方法");
    } 
    
    public void destroyMethod(){
        System.out.println("第五步:执行destroy-method销毁方法");
    }
}
  1. 在Spring配置文件中,指定init-method和destroy-method方法
    <bean id="service" class="Test_bean.Service" init-method="initMethod" destroy-method="destroyMethod">
        <property name="name" value="offer"></property>
    </bean>
  1. 创建测试类,进行测试

注意:需要关闭IOC容器才会执行destroy-method方法,并且接口类需要上升到ConfigurableApplicationContext才会提供close( )方法

public class Springtest {

    @Test
    public void test(){
        ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        Service service = context.getBean("service", Service.class);
        System.out.println("第四步:使用对象:"+service);
        context.close();
    }
}
  1. 测试结果
第一步:执行无参数构造方法创建bean实例
第二步:调用setter方法为属性赋值
第三步:执行init-method初始化方法
第四步:使用对象:Test_bean.Service@40a4337a
第五步:执行destroy-method销毁方法

3.2、bean的生命周期:添加了bean的后置处理器

1、bean的后置管理器

  1. bean的后置处理器允许在调用初始化方法前后对bean进行额外的处理
  2. bean的后置处理器对IOC容器里的所有bean实例逐一处理,而非单一实例。
  3. bean后置处理器时需要实现接口:org.springframework.beans.factory.config.BeanPostProcessor。在初始化方法被调用前后,Spring将把每个bean实例分别传递给上述接口的以下两个方法:
    • postProcessBeforeInitialization(Object, String)
    • postProcessAfterInitialization(Object, String)

2、添加bean的后置处理器后bean的生命周期

  1. 通过构造器创建bean实例(无参数构造)
  2. 为bean的属性设置值和对其他bean引用(调用set方法)
  3. 将bean实例传递给bean后置处理器的postProcessBeforeInitialization()方法
  4. 调用bean的初始化的方法(需要进行配置初始化的方法)
  5. 将bean实例传递给bean后置处理器的postProcessBeforeInitialization()方法
  6. bean可以使用了(对象获取到了)
  7. 当容器关闭时候,调用bean的销毁的方法(需要进行配置销毁的方法)

3、 代码演示:

  1. 创建MyBean类,实现BeanPostProcessor接口,重写postProcessBeforeInitialization和postProcessAfterInitialization方法
public class MyBean 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;
    }
}
  1. 创建Service类
public class Service {
    private String name;

    public Service(){
        System.out.println("第一步:执行无参数构造方法创建bean实例");
    }

    public void setName(String name) {
        this.name = name;
        System.out.println("第二步:调用setter方法为属性赋值");
    }

    public void initMethod(){
        System.out.println("第四步:执行init-method初始化方法");
    }

    public void destroyMethod(){
        System.out.println("第七步:执行destroy-method销毁方法");
    }
}
  1. 在Spring配置文件中实例化自定义的MyBean后置处理器
    <bean id="service" class="Test_bean.Service" init-method="initMethod" destroy-method="destroyMethod">
        <property name="name" value="offer"></property>
    </bean>
    <bean id="mybean" class="FactoryBean.MyBean"></bean>
  1. 创建测试类
public class Springtest {

    @Test
    public void test(){
        ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        Service service = context.getBean("service", Service.class);
        System.out.println("第六步:使用对象:"+service);
        context.close();
    }
}
  1. 测试结果
第一步:执行无参数构造方法创建bean实例
第二步:调用setter方法为属性赋值
第三步:执行postProcessBeforeInitialization方法
第四步:执行init-method初始化方法
第五步:执行postProcessAfterInitialization方法
第六步:使用对象:Test_bean.Service@4c402120
第七步:执行destroy-method销毁方法

4、Xml的自动装配

1、概念:根据指定的装配规则,不需要明确指定,Spring自动将匹配的属性值注入bean中

2、在Spring配置文件中,通过autowire标签设置自动装配的方式:

  1. byType:将类型匹配的bean作为属性注入到另一个bean中。若IOC容器中有多个与目标bean类型一致的bean,Spring将无法判定那个bean最合适该属性,所以不能执行自动装配
  2. byName:必须将目标bean的名称和属性名设置的完全相同
  3. constructor:当bean中存在多个构造器时,此种自动装配方式将会很复杂

3、代码演示:

  1. 创建两个类Service和Dao类,在Service类中以Dao类型作为属性
public class Dao {

    private String name;

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

    public void print(){
        System.out.println("my name is "+name);
    }
}
public class Service {
    private Dao dao;

    public void setDao(Dao dao) {
        this.dao = dao;
    }

    public void print(){
        dao.print();
    }

}
  1. 在Spring配置文件中设置自动装配的方式
    <bean id="service" class="Test_bean.Service" autowire="byName"></bean>
        <!--byName:需要下面的bean的id值与Service类中的属性值相同-->
    <bean id="dao" class="Test_bean.Dao">
        <property name="name" value="offer"></property>
    </bean>
    <bean id="service" class="Test_bean.Service" autowire="byType"></bean>
    <bean id="dao" class="Test_bean.Dao">
        <property name="name" value="offer"></property>
    </bean>
    <!--byType需要注意的是,如果有多个Dao类的bean,Spring就无法判断注入那个bean-->
    <!--<bean id="dao1" class="Test_bean.Dao">-->
    <!--<property name="name" value="offer"></property>-->
    <!--</bean>-->
  1. 创建测试类,进行测试
public class Springtest {

    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        Service service = context.getBean("service", Service.class);
        service.print();
    }
}
  1. 测试结果:
my name is offer

❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤
若对Spring基础知识感兴趣的可以关注一下博主,我会持续更新Spring基础知识(一边学习一边记录),一起进步,有错误的地方也可以在评论区指出来喔,谢谢大家啦!!!

  • 15
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

offer冲冲冲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值