欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring 框架基础(02):Bean的生命周期,作用域,装配总结

程序员文章站 2023-04-05 16:21:35
本文源码: "GitHub·点这里" || "GitEE·点这里" 一、装配方式 Bean的概念:Spring框架管理的应用程序中,由Spring容器负责创建,装配,设置属性,进而管理整个生命周期的对象,称为Bean对象。 1、XML格式装配 Spring最传统的Bean的管理方式。 配置方式 测试 ......

本文源码:github·点这里 || gitee·点这里

一、装配方式

bean的概念:spring框架管理的应用程序中,由spring容器负责创建,装配,设置属性,进而管理整个生命周期的对象,称为bean对象。

1、xml格式装配

spring最传统的bean的管理方式。

  • 配置方式
<bean id="userinfo" class="com.spring.mvc.entity.userinfo">
    <property name="name" value="cicada" />
</bean>
  • 测试代码
applicationcontext context01 = new classpathxmlapplicationcontext("/bean-scan-02.xml");
userinfo userinfo = (userinfo)context01.getbean("userinfo") ;
system.out.println(userinfo.getname());

2、注解扫描

在实际开发中:通常使用注解 取代 xml配置文件。

  • 常见注解
@component <==> <bean class="class">
@component("id") <==> <bean id="id" class="class">
@repository :mvc架构中dao层bean的注解
@service:mvc架构中service层bean的注解
@controller:mvc架构中controller层bean的注解
  • 使用案例
// 1、注解代码块
@component("infoservice")
public class infoserviceimpl implements infoservice {
    @override
    public void printname(string name) {
        system.out.println("name:"+name);
    }
}

// 2、配置代码块
@componentscan // 组件扫描注解
public class beanconfig {

}
  • 测试代码
@runwith(springjunit4classrunner.class)
@contextconfiguration(classes = beanconfig.class)
public class test01 {
    @autowired
    private infoservice infoservice ;
    @test
    public void test1 (){
        infoservice.printname("cicada");
        system.out.println(infoservice==infoservice);
    }
}

3、xml配置扫描

上面使用 componentscan 注解,也可在配置文件进行统一的配置,效果相同,还简化代码。

<context:component-scan base-package="com.spring.mvc" />

4、java代码装配

这种基于configuration注解,管理bean的创建,在springboot和springcloud的框架中,十分常见。

  • 配置类代码
@configuration // 配置类注解
public class userconfig {
    @bean
    public userinfo userinfo (){
        system.out.println("userinfo...");
        return new userinfo() ;
    }
}
  • 测试代码
@runwith(springjunit4classrunner.class)
@contextconfiguration(classes = userconfig.class)
public class test03 {
    @autowired
    private userinfo userinfo ;
    @autowired
    private userinfo userinfo1 ;
    @test
    public void test1 (){
        /*
         * userinfo...
         * true
         */
        system.out.println(userinfo==userinfo1);
    }
}

二、属性值设置

上面是bean的装配几种常见方式,下面来看看bean属性值设置,这里就基于xml配置的方式。

1、基础类型和集合

  • 配置代码
<!-- 配置employee公共属性 -->
<bean id="emp1" class="com.spring.mvc.entity.employee">
    <property name="name" value="cicada" />
    <property name="id" value="1" />
</bean>
<bean id="emp2" class="com.spring.mvc.entity.employee">
    <property name="name" value="smile" />
    <property name="id" value="2" />
</bean>
<!-- 配置department属性 -->
<bean id="department" class="com.spring.mvc.entity.department">
    <!-- 普通属性值的注入 -->
    <property name="name" value="it部门" />
    <!-- 给数组注入值 -->
    <property name="empname">
        <list>
            <value>empname1</value>
            <value>empname2</value>
            <value>empname3</value>
        </list>
    </property>
    <!-- 给list注入值:可以存放相同的值 -->
    <property name="emplist">
        <list>
            <ref bean="emp1"/>
            <ref bean="emp2"/>
            <ref bean="emp1"/>
        </list>
    </property>
    <!-- 配置set属性,相同的对象会被覆盖 -->
    <property name="empset">
        <set>
            <ref bean="emp1"/>
            <ref bean="emp2"/>
            <ref bean="emp1"/>
        </set>
    </property>
    <!-- 配置map属性,key相同的话,后面的值会覆盖前面的 -->
    <property name="empmap">
        <map>
            <entry key="1" value-ref="emp1" />
            <entry key="2" value-ref="emp2" />
            <entry key="2" value-ref="emp1" />
        </map>
    </property>
    <!-- 配置属性集合 -->
    <property name="pp">
        <props>
            <prop key="pp1">hello</prop>
            <prop key="pp2">world</prop>
        </props>
    </property>
</bean>
  • 测试代码
public class test05 {
    @test
    public void test01 (){
        applicationcontext context = new classpathxmlapplicationcontext("/bean-value-03.xml");
        department department = (department) context.getbean("department");
        system.out.println(department.getname());
        system.out.println("--------------------->string数组");
        for (string str : department.getempname()){
            system.out.println(str);
        }
        system.out.println("--------------------->list集合");
        for (employee smp : department.getemplist()){
            system.out.println(smp.getid()+":"+smp.getname());
        }
        system.out.println("--------------------->set集合");
        for (employee emp : department.getempset()){
            system.out.println(emp.getid()+":"+emp.getname());
        }
        system.out.println("--------------------->map集合");
        for (map.entry<string, employee> entry : department.getempmap().entryset()){
            system.out.println(entry.getkey()+":"+entry.getvalue().getname());
        }
        system.out.println("--------------------->properties");
        properties pp = department.getpp();
        system.out.println(pp.get("pp1"));
        system.out.println(pp.get("pp2"));
    }
}

2、配置构造函数

根据配置的参数个数和类型,去映射并加载bean的构造方法。

  • 配置代码
<!-- 这里配置2个参数,所有调用2个参数的构造函数 -->
<bean id="employee" class="com.spring.mvc.entity.employee">
    <constructor-arg index="0" type="java.lang.string" value="cicada"/>
    <constructor-arg index="1" type="int" value="1"/>
</bean>
  • 测试代码
public class test06 {
    @test
    public void test01 (){
        applicationcontext context = new classpathxmlapplicationcontext("/bean-value-04.xml");
        employee employee = (employee) context.getbean("employee");
        system.out.println(employee.getid()+":"+employee.getname());
    }
}

3、配置继承关系

  • 配置代码
<!-- 配置父类信息 -->
<bean id="student" class="com.spring.mvc.entity.student">
    <property name="name" value="spring" />
    <property name="age" value="22" />
</bean>
<!-- 配置子类信息 -->
<bean id="grade" class="com.spring.mvc.entity.grade">
    <!-- 覆盖 -->
    <property name="name" value="summer" />
    <property name="degree" value="大学" />
</bean>
  • 测试代码
public class test07 {
    @test
    public void test01 (){
        applicationcontext context = new classpathxmlapplicationcontext("/bean-value-05.xml");
        grade grade = (grade) context.getbean("grade");
        /* summer;0;大学  */
        system.out.println(grade.getname()+";"+grade.getage()+";"+grade.getdegree());
    }
}

三、作用域

作用域:用于确定spring创建bean实例个数,比如单例bean,原型bean,等等。

类型 说明
singleton ioc容器仅创建一个bean实例,ioc容器每次返回的是同一个单例bean实例,默认配置。
prototype ioc容器可以创建多个bean实例,每次返回的bean都是新的实例。
request 每次http请求都会创建一个新的bean,适用于webapplicationcontext环境。
session 同一个http session共享一个bean实例。不同http session使用不同的实例。
global-session 同session作用域不同的是,所有的session共享一个bean实例。

四、生命周期

在spring框架中bean的生命周期非常复杂,过程大致如下:实例化,属性加载,初始化前后管理,销毁等。下面基于一个案例配置,会更加的清楚。

1、编写beanlife类

public class beanlife implements beannameaware {
    private string name ;
    public string getname() {
        return name;
    }
    public void setname(string name) {
        system.out.println("设置名称:"+name);
        this.name = name;
    }
    @override
    public void setbeanname(string value) {
        system.out.println("beannameaware..setname:"+value);
    }
    public void initbean() {
        system.out.println("初始化bean..");
    }
    public void destroybean() {
        system.out.println("销毁bean..");
    }
    public void usebean() {
        system.out.println("使用bean..");
    }
    @override
    public string tostring() {
        return "beanlife [name = " + name + "]";
    }
}

2、定制加载过程

实现beanpostprocessor接口。

public class beanlifepostprocessor implements beanpostprocessor {
    // 初始化之前对bean进行增强处理
    @override
    public object postprocessbeforeinitialization(object obj, string beanname) throws beansexception {
        system.out.println("初始化之前..."+beanname);
        return obj ;
    }
    // 初始化之后对bean进行增强处理
    @override
    public object postprocessafterinitialization(object obj, string beanname) throws beansexception {
        system.out.println("初始化之后..."+beanname);
        // 改写bean的名称
        if (obj instanceof beanlife){
            beanlife beanlife = (beanlife)obj ;
            beanlife.setbeanname("mybeanlifetwo");
            return beanlife ;
        }
        return obj ;
    }
}

3、配置文件

<!-- 加载bean的处理器 -->
<bean class="com.spring.mvc.beanlifepostprocessor" />
<!-- 指定初始化和销毁方法 -->
<bean id="beanlife" class="com.spring.mvc.entity.beanlife"
    init-method="initbean" destroy-method="destroybean">
    <property name="name" value="mybeanlifeone" />
</bean>

4、测试过程

  • 测试代码
public class test08 {
    @test
    public void test01 (){
        applicationcontext context = new classpathxmlapplicationcontext("/bean-value-06.xml");
        beanlife beanlife = (beanlife) context.getbean("beanlife");
        system.out.println("测试结果beanlife:"+beanlife.getname()) ;
        beanlife.usebean();
        // 关闭容器
        ((abstractapplicationcontext) context).close();
    }
}
  • 输出结果
1、设置名称:mybeanlifeone
2、beannameaware..setname:beanlife
3、初始化之前...beanlife
4、初始化bean..
5、初始化之后...beanlife
6、beannameaware..setname:mybeanlifetwo
7、测试结果beanlife:mybeanlifeone
8、使用bean..
9、销毁bean..

这里梳理bean的生命周期,过程十分清晰。

五、源代码地址

github·地址
https://github.com/cicadasmile/spring-mvc-parent
gitee·地址
https://gitee.com/cicadasmile/spring-mvc-parent

Spring 框架基础(02):Bean的生命周期,作用域,装配总结