SpringBean的装配与注入

文章目录

一、Spring的特点

  • 方便解耦,简化开发
  • 方便集成各种优秀框架
  • AOP编程的支持
  • 降低JavaEE API的使用难度
  • 声明式事务的支持
  • 开源项目
  • 方便程序测试

体系结构图

SpringBean的装配与注入

; 核心概念

控制反转(IOC:Inversion of Control):将对象的控制权由硬编码的程序转交给Spring容器

解释:传统的JavaSE程序通过new关键字进行创建对象,对象的控制权在硬编码的Java程序。实现了IOC设计的Spring程序,对象的控制权在Spring容器。

Spring配置文件的bean节点相关属性

  • Spring的bean节点中具备很多属性,如下表

属性名称说明id唯一标识;方便在别的地方可以找到这个对象class类的全称,
注意 全称是包名加上类名

lazy-init是否延迟加载init-method对象初始化完成之后就执行的方法destroy-method当前对象被销毁之前Spring会自动调用的方法scope单例还是多例depends-on强制要求实例化这个bean之前必须先实例化另一个bean

  • 其中还有property子节点,property子节点的属性如下

属性名称说明name属性名value属性值ref对象类型的引入

  • 示例代码:
  • Spring配置文件
<bean   id="user" class="com.iflytek.entity.User"   init-method="fun1"
destroy-method="fun2"   scope="prototype" depends-on="dept" >
<property   name="name" value="张三">property>
<property   name="age" value="18">property>
bean>
<bean   id="dept"   class="com.iflytek.entity.Dept">bean>
  • 测试类

public static void   main(String[] args) {

ApplicationContext   ctx=new ClassPathXmlApplicationContext("ApplicationContext.xml");

User   user=(User)ctx.getBean("user");

System.out.println(user);

}
  • 扩展:Spring的上下文也可以同时加载多个Spring的配置文件,例:
ApplicationContext   ctx=new ClassPathXmlApplicationContext("a.xml","b.xml");

ApplicationContext   ctx=new ClassPathXmlApplicationContext(new String[] {"a.xml","b.xml"});

二、依赖注入的三种方式

  • 实体类Customer:

package com.entity;

public class Customer {

    private String uname;

    private BankCard bankCard;

    public String getUname() {

        return uname;

    }

    public void setUname(String uname) {

        this.uname = uname;

    }

    public BankCard getBankCard() {

        return bankCard;

    }

    public void setBankCard(BankCard   bankCard) {

        this.bankCard = bankCard;

    }

    public Customer(String uname) {

        this.uname = uname;

    }

    public Customer() {

        super();

    }

    public Customer(String uname, BankCard   bankCard) {

        super();

        this.uname = uname;

        this.bankCard = bankCard;

    }

}
  • 实体类BankCard
package com.entity;

public class BankCard {

    private String bcId;

    private IdCard ic;

    public String getBcId() {

        return bcId;

    }

    public void setBcId(String bcId) {

        this.bcId = bcId;

    }

    public IdCard getIc() {

        return ic;

    }

    public void setIc(IdCard ic) {

        this.ic = ic;

    }

}
  • 实体类IdCard
package com.entity;

public class IdCard {

    private String idCard;

    public String getIdCard() {

        return idCard;

    }

    public void setIdCard(String idCard) {

        this.idCard = idCard;

    }

}

1、Set方法注入


<bean id="cust"   class="com.entity.Customer">

  <property name="uname"   value="张学友">property>

  <property name="bankCard"   ref="bc">property>

bean>

<bean   id="bc" class="com.entity.BankCard">

  <property name="bcId"   value="123456789">property>

  <property name="ic"   ref="icc">property>

bean>

<bean   id="icc" class="com.entity.IdCard">

  <property name="idCard"   value="1111111111111">property>

bean>

2、构造方法注入

注意:一定要有该构造方法,index:参数的位置,ref:对象类型的引用,type:参数对象的类型,value:值


<bean id="cust22"   class="com.entity.Customer">

  <constructor-arg index="0"   type="String" value="刘德华">constructor-arg>

bean>

<bean id="cust322"   class="com.entity.Customer">

  <constructor-arg index="0"   type="String" value="刘德华2">constructor-arg>

  <constructor-arg index="1"   type="com.entity.BankCard" ref="bc">constructor-arg>

bean>

3、 静态工厂注入

<bean   id="qa" class="com.factory.BankCardFactory"   factory-method="createBankCard">bean>

<bean   id="cust4" class="com.entity.Customer">

           <property name="uname"   value="周杰伦">property>

           <property   name="bankCard" ref="qa">property>

bean>

注意点:
需要新建一个类,类中包含一个静态方法,factory-method :静态方法名

package com.factory;

import com.entity.BankCard;

public class BankCardFactory {

    public static BankCard createBankCard() {

        return new BankCard();

   }

}

三、复杂数据类型注入

  • 创建班级实体类和学生实体类
    SpringBean的装配与注入

; 1、 数组类型注入


<bean id="c1" class="com.entity.Clazz">

  <property name="clazzName"   value="Java6班">property>

  <property name="sname">

            <list>

                       <value>jack1value>

                       <value>jack2value>

                       <value>jack3value>

            list>

  property>

 bean>

2、List集合类型注入


<bean id="c1" class="com.entity.Clazz">

        <property   name="clazzName" value="Java6班">property>

        <property   name="stus">

            <list>

                <ref   bean="s1"/>

                <ref   bean="s2"/>

                <ref   bean="s3"/>

            list>

        property>

bean>

<bean id="s1"   class="com.entity.Student">

            <property   name="sname" value="jack1">property>

bean>

<bean id="s2" class="com.entity.Student">

            <property   name="sname" value="jack2">property>

bean>

<bean id="s3"   class="com.entity.Student">

            <property   name="sname" value="jack3">property>

bean>

3、Set集合类型注入


<bean id="c1" class="com.entity.Clazz">

        <property   name="clazzName" value="Java6班">property>

        <property   name="stuSet">

            <set>

                <ref   bean="s1"/>

                <ref   bean="s2"/>

                <ref   bean="s3"/>

            set>

        property>

bean>

  <bean id="s1"   class="com.entity.Student">

            <property   name="sname" value="jack1">property>

  bean>

  <bean id="s2"   class="com.entity.Student">

            <property   name="sname" value="jack2">property>

  bean>

  <bean id="s3"   class="com.entity.Student">

            <property   name="sname" value="jack3">property>

           bean>

4、Map集合类型注入

<bean   id="c1" class="com.entity.Clazz">

        <property   name="clazzName" value="Java6班">property>

        <property   name="stuMap">

            <map>

                <entry key="1"   value-ref="s1">entry>

                <entry key="2"   value-ref="s2">entry>

                <entry key="3"   value-ref="s3">entry>

            map>

        property>

    bean>

    <bean id="s1"   class="com.entity.Student">

            <property   name="sname" value="jack1">property>

  bean>

  <bean id="s2"   class="com.entity.Student">

            <property   name="sname" value="jack2">property>

  bean>

  <bean id="s3"   class="com.entity.Student">

            <property   name="sname" value="jack3">property>

           bean>

5、Date时间类型注入

  • 在学生实体类中添加属性生日

package com.entity;

import java.util.Date;

//学生类

public class Student {

  private String sname;//学生姓名

  private Date sbirth;

  public Date getSbirth() {

            return sbirth;

  }

  public void setSbirth(Date sbirth) {

            this.sbirth = sbirth;

  }

  public String getSname() {

            return sname;

  }

  public void setSname(String sname) {

            this.sname = sname;

  }

  @Override

  public String toString() {

            return "Student [sname="   + sname + "]";

  }

}
  • Spring配置文件中

<bean id="s4"   class="com.entity.Student">

  <property name="sbirth" >

            <bean   factory-bean="sdf" factory-method="parse">

                       <constructor-arg   value="2020-09-09">constructor-arg>

            bean>

  property>

bean>

<bean id="sdf"   class="java.text.SimpleDateFormat">

  <constructor-arg index="0"   name="pattern"   value="yyyy-MM-dd">constructor-arg>

bean>

四、Spring的自动装配

1、之前注入的写法


<bean id="cust"   class="com.entity.Customer">

  <property name="uname"   value="张学友">property>

  <property name="bankCard"   ref="bc">property>

bean>

<bean id="bc"   class="com.entity.BankCard">

  <property name="bcId"   value="123456789">property>

bean>

2、 升级版——>将ref移除掉(根据类型来自动装配——>byType)

<bean id="cust"   class="com.entity.Customer" autowire="byType">

  <property   name="uname" value="张学友">property>

bean>

<bean id="bc"   class="com.entity.BankCard">

  <property   name="bcId" value="123456789">property>

bean>

3、根据类型来自动装配的弊端

当Spring的主配置文件存在两个相同类型时,例如上述例子注入了两个BankCard类型的对象即会产生问题


<bean id="bc"   class="com.entity.BankCard">

  <property   name="bcId" value="1111 2222 3333   5555">property>

bean>

<bean id="bankCard"   class="com.entity.BankCard">

  <property   name="bcId" value="1111 2222 3333   4444">property>

bean>

<bean id="cust"   class="com.entity.Customer" autowire="byType">

  <property   name="uname" value="jack">property>

bean>

4、错误信息

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.entity.BankCard' available: expected single matching bean but found 2: bc,bankCard

5、 解释

因为采用的是根据类型来进行自动装配,但是在装配的过程中发现有两个BankCard的类型可以装入,具体装配哪一个就无法确定了,所以就会出现异常信息

6、 解决方法

将根据类型自动装配改成根据名称来进行自动装配——>(byName);根据属性的名称与bean节点id的值是否一致来进行自动装配,即Customer中BankCard的属性名称bankCard;那么即会自动装配进id值为bankCard的bean节点对象


<bean id="bc"   class="com.entity.BankCard">

  <property   name="bcId" value="1111 2222 3333   5555">property>

bean>

<bean id="bankCard"   class="com.entity.BankCard">

  <property   name="bcId" value="1111 2222 3333   4444">property>

bean>

<bean id="cust"   class="com.entity.Customer" autowire="byName">

  <property   name="uname" value="jack">property>

bean>

7、 自动装备再升级

将autowire的属性写入bean中即表示这个bean的注入为自动注入,同时也可以写在Spring的命名空间上,表示全文件都采用自动注入

8、 总结

Spring的自动装配共有两种方式,详情见下表

自动装配特点byType根据类型来自动注入对象的文字属性 例如:Customer类的bankCard属性的类型BankCard spring会自动查找spring配置文件中所有符合BankCard类型的bean对象;如果找到一个符合类型的或多个类型都符合,则报错byName根据名称来自动注入对象的子对象属性 ;例如:Customer类中有属性名叫bankCard和spring文件中注入的BankCard类的bean的id相同,则自动注入

Original: https://blog.csdn.net/qq_54351538/article/details/127794592
Author: wangkay88
Title: SpringBean的装配与注入

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/653827/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球