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

Spring IOC容器装配Bean_基于XML配置方式

程序员文章站 2022-06-15 17:38:04
开发所需jar包 实例化Bean的四种方式 1.无参数构造器 (最常用) 2.静态工厂方法 3.实例(非静态)工厂方法 4.FactoryBean方式(底层源码用的多) Bean的作用域 由spring创建的bean对象在什么情况下有效 项目开发中通常会使用:singleton 单例、 protot ......

开发所需jar包
Spring IOC容器装配Bean_基于XML配置方式

实例化bean的四种方式

1.无参数构造器 (最常用)

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
        
    <!--1.无参构造函数
    在实例化的时候,自动调用默认的构造器,相当于mybean mybean01 = new mybean();
    -->
     <!--bean:告诉spring容器,哪些对象(bean)需要交给spring容器进行管理
    id/name:该bean的“唯一”标识符
    class:该bean的完整类名(spring容器底层可以使用反射创建对象)
    -->
    <bean id="mybean01" class="com.igeekhome.bean.mybean"></bean>
</beans>
public class mybean {
    public mybean() {
        system.out.println("mybean...无参构造函数被调用...");
    }
}

2.静态工厂方法

 <!--2.静态工厂方法
    myfactory01.getbean()
    factory-method:指定静态的工厂方法
    -->
    <bean id="mybean02" class="com.igeekhome.bean.myfactory01" factory-method="getbean"></bean>
public class myfactory01 {
    //静态工厂方法
    public static mybean getbean() {
        return new mybean();
    }
}

3.实例(非静态)工厂方法

<!--3.非静态工厂方法
    new myfatory02().getbean
    -->
    <bean id="myfatory" class="com.igeekhome.bean.myfactory02"></bean>
    <!--
    factory-bean:工厂对象的引用
    factory-method: 工厂方法名称
    -->
    <bean id="mybean03" factory-bean="myfatory" factory-method="getbean"></bean>
public class myfactory02 {
    //非静态工厂方法
    public mybean02 getbean() {
        return new mybean02();
    }
}

4.factorybean方式(底层源码用的多)

<!--4.factorybean
    myfactorybean:spring会先检查该类是否实现了factorybean接口,如果没有实现,则直接创建该对象并添加至容器中
    如果实现了factorybean接口,则调用getobject方法,并将该方法返回值对象添加至容器中
    -->
    <bean id="mybean04" class="com.igeekhome.bean.myfactorybean"></bean>
//创建工厂对象实现factorybean<bean4>的接口
public class myfactorybean implements factorybean<mybean03> {//泛型:你要返回什么类型的对象,泛型就是什么
    @override
    public mybean getobject() throws exception {
        return new mybean();
    }

    @override
    public class<?> getobjecttype() {
        return mybean.class;
    }
}

bean的作用域

由spring创建的bean对象在什么情况下有效

Spring IOC容器装配Bean_基于XML配置方式

项目开发中通常会使用:singleton 单例、 prototype多例

  • singleton: 在一个spring容器中,对象只有一个实例(默认值)
  • prototype: 在一个spring容器中,存在多个实例,每次getbean 返回一个新的实例
<!-- bean的作用范围
       scope:配置作用范围的,默认值就是singleton单例
     -->
<!-- 单例 -->
<!-- <bean id="singletonbean" class="com.igeek.scope.singletonbean"></bean> 等价于 -->
    <bean id="singletonbean" class="com.igeek.scope.singletonbean" 
    scope="singleton"></bean>
    
    <!-- 多例 -->
    <bean id="prototypebean" class="com.igeek.scope.prototypebean" 
scope="prototype"></bean>

bean的初始化和销毁方法

通过 init-method属性 指定初始化后的调用方法
通过 destroy-method属性 指定销毁对象前的方法

 <!--
    init-method:指定初始化方法
    destroy-method: 指定销毁触发方法
    -->
    <bean id="lifecycle" class="com.igeekhome.bean.lifecyclebean" scope="singleton" init-method="initmethod" destroy-method="destroymethod"></bean>
public class lifecyclebean {

    public lifecyclebean() {
        system.out.println("构造函数...");
    }

    public void initmethod() {
        //...执行初始化操作
        system.out.println("init...method...");
    }

    public void destroymethod() {
        system.out.println("destroy...method...");
    }
}
销毁方法的执行必须满足两个条件
  • 单例(singleton)的bean才会可以手动销毁
  • 必须手动关闭容器(调用close的方法)时,才会执行手动销毁的方法

测试初始化和销毁方法:

public class test03 {
    private applicationcontext ac = null;
    @before
    public void before() {
        ac = new classpathxmlapplicationcontext("applicationcontext.xml");
    }
    @test
    public void method01() {
        lifecyclebean lifecyclebean = ac.getbean("lifecycle", lifecyclebean.class);
        //关闭ioc容器
        ((classpathxmlapplicationcontext) ac).close();
    }
}

后处理bean(beanpostprocessor接口)

后处理bean也称之为bean的后处理器,作用是:在bean初始化的前后,对bean对象进行增强。它既可以增强一个指定的bean,也可以增强所有的bean,底层很多功能(如aop等)的实现都是基于它的,spring可以在容器中直接识别调用

////bean的后处理器:对bean进行增强,可以实现,对所有,或某个bean的初始化进行增强
public class mybeanpostprocessor implements beanpostprocessor{
    /*bean实例化之前
       bean:对象
       beanname: bean的id/name
     */
    //初始化时(之前)调用的
    public object postprocessbeforeinitialization(object bean, string beanname)throws beansexception {
        //system.out.println(beanname+"在初始化前开始增强了");
       //如何只增强一个bean
       if(beanname.equals("lifecyclebean")){
           system.out.println(beanname+"在初始化前开始增强了");
       }
       return bean;//放行
    }
    
    //初始化时(之后)调用
    public object postprocessafterinitialization(object bean, string beanname)throws beansexception {
        //system.out.println(beanname+"在初始化后开始增强了");
       if(beanname.equals("lifecyclebean")){
           system.out.println(beanname+"在初始化后开始增强了");
       }
       return bean;
    }
}

bean属性的依赖注入(di)

1.setter方法属性注入

public class person {
    private int no;
    private string name;
    private boolean status;
    private car car;

    public person() {
    }

    public int getno() {
        return no;
    }

    public void setno(int no) {
        this.no = no;
    }

    public string getname() {
        return name;
    }

    public void setname(string name) {
        this.name = name;
    }

    public boolean isstatus() {
        return status;
    }

    public void setstatus(boolean status) {
        this.status = status;
    }

    public car getcar() {
        return car;
    }

    public void setcar(car car) {
        this.car = car;
    }

    @override
    public string tostring() {
        return "person{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", status=" + status +
                ", car=" + car +
                '}';
    }

    public person(int no, string name, boolean status, car car) {
        this.no = no;
        this.name = name;
        this.status = status;
        this.car = car;
    }
}

public class car {
    private string no;
    private string brand;
    private double price;

    public string getno() {
        return no;
    }

    public void setno(string no) {
        this.no = no;
    }

    public string getbrand() {
        return brand;
    }

    public void setbrand(string brand) {
        this.brand = brand;
    }

    public double getprice() {
        return price;
    }

    public void setprice(double price) {
        this.price = price;
    }

    @override
    public string tostring() {
        return "car{" +
                "no='" + no + '\'' +
                ", brand='" + brand + '\'' +
                ", price=" + price +
                '}';
    }

    public car() {
    }

    public car(string brand, double price) {
        this.brand = brand;
        this.price = price;
    }

    public car(string no, string brand, double price) {
        this.no = no;
        this.brand = brand;
        this.price = price;
    }
}
<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="person" class="com.igeekhome.di.person">
        <!--setter注入:前提满足javabean规范(提供setter方法)-->
        <!--property:setter注入
            name:属性名称 (具体来说是set方法名的首字母小写)xyz -> 默认会调用setxyz()
            value:简单值
            ref:注入的bean的id 将容器中的一个bean注入到另外一个bean中
        -->
        <property name="no" value="123"></property>
        <property name="name" value="张三"></property>
        <property name="status" value="true"></property>
        <property name="car" ref="car"></property>
        <!--等价-->
        <!--<property name="car">
            <ref bean="car"></ref>
        </property>-->
    </bean>

    <bean id="car" class="com.igeekhome.di.car">
        <property name="brand" value="宝马"></property>
        <property name="price" value="66666"></property>
    </bean>

</beans>

2.构造器参数注入

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="car" class="com.igeekhome.di.car">
        <!--使用constructor构造注入
        value:
        ref:  同上
        type: 构造参数类型 如果是引用 需要写完整类名 (每个字段不一致)
        index: 构造参数的索引位置 从0开始
        name: 构造参数的名称
        -->
        <constructor-arg name="brand" value="宝马"></constructor-arg>
        <constructor-arg name="price" value="66666"></constructor-arg>
        <constructor-arg name="no" value="001"></constructor-arg>
    </bean>

    <bean id="person" class="com.igeekhome.di.person">
        <constructor-arg index="0" value="111"></constructor-arg>
        <constructor-arg index="1" value="李四"></constructor-arg>
        <constructor-arg index="2" value="false"></constructor-arg>
        <constructor-arg index="3" ref="car"></constructor-arg>
    </bean>

</beans>

3.p名称空间

为简化xml文件的配置,spring2.5版本开始引入了一个新的p名称空间。简单的说,它的作用是为了简化setter方法属性依赖注入配置的,它不是真正的名称空间

它的使用方法:

p:<属性名>="xxx" 引入常量值
p:<属性名>-ref="xxx" 引用其它bean对象
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemalocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--p命名空间注入:
    前提:基于setter注入
    p:属性 = ""
    p:属性-ref = ""
    -->
    <bean id="person" class="com.igeekhome.di.person" p:name="张三" p:no="002" p:status="false" p:car-ref="car">
    </bean>
    <bean id="car" class="com.igeekhome.di.car" p:brand="qq" p:price="66666">
    </bean>
</beans>

4.spel表达式

spel(spring expression language)是一种表达式语言,它是spring3.x版本的新特性。 它的作用是:支持在运行时操作和查询对象,其语法类似统一的el语言,但是spel提供了额外的功能,功能更强大

语法: #{…} , 引用另一个bean 、属性、 方法
spel表达式的使用功能比较多,bean操作相关的通常有:

#{beanid} 引用bean(具体对象)
#{beanid.属性} 引用bean的属性
#{beanid.方法(参数)} 调用bean的方法
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemalocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="person" class="com.igeekhome.di.person" p:name="张三" p:no="002" p:status="false" p:car="#{car2}">
    </bean>
    <bean id="car" class="com.igeekhome.di.car" p:brand="qq" p:price="66666">
    </bean>
    <bean id="car2" class="com.igeekhome.di.car" p:no="#{car.no}" p:brand="#{car.brand.touppercase()}" p:price="#{car.price}">
    </bean>
</beans>