SpringBean的装配与注入


一、Spring的特点

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

体系结构图

在这里插入图片描述

核心概念

控制反转(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 是一个接口;不可直接new;可导入源码查看,源码在下载spring的jar中resources结尾的jar包,所以创建实现类对象

//参数为:spring配置文件的文件名称

//注意:ApplicationContext初始化之时;配置的需要spring容器帮助创建的对象也就创建了

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

//根据id值来获取spring容器帮助你创建的User对象,需要强转

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

//打印user对象的相关对象

System.out.println(user);

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

//      ((ClassPathXmlApplicationContext)ctx).close();    

}
  • 扩展: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();

   }

}

三、复杂数据类型注入

  • 创建班级实体类和学生实体类
    在这里插入图片描述

1、 数组类型注入


<!--Array与list节点都可以,但是一般推荐使用list-->

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

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

  <property name="sname">

  <!--   

            <array>

                       <value>jack1</value>

                       <value>jack2</value>

                       <value>jack3</value>

            </array>

            -->

            <list>

                       <value>jack1</value>

                       <value>jack2</value>

                       <value>jack3</value>

            </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" >

            <!-- 下列配置 类似于下列转换

            SimpleDateFormat sdf=new   SimpleDateFormat("yyyy-MM-dd");

            sdf.parse("2020-09-09");  

            -->

            <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相同,则自动注入
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

wangkay88

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

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

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

打赏作者

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

抵扣说明:

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

余额充值