Spring DI相关内容

1 property或constructor-arg基础配置

<property/constructor-arg name="所要注入属性的属性名" value="基本数据类型" ref="引用数据类型对应bean的id">

 

2 setter注入

//可选依赖使用setter注入进行,灵活性强。
//推荐使用setter注入。

(1) 注入引用数据类型

见Spring DI快速入门

(2) 注入简单数据类型

<1> 准备需要被创建的类,声明属性并提供setter方法
//在BookDaoImpl类中声明对应的简单数据类型的属性,并提供对应的setter方法。

public class BookDaoImpl implements BookDao {
    private String str;
    private int i;
    //setter方法
    public void setI(int i) {
        this.i = i;
    }
    //setter方法
    public void setStr(String str) {
        this.str= str;
    }
    public void save() {
        System.out.println("BookDaoImpl,"+str+","+i);
    }
}

<2> 配置文件中进行注入配置

<!--在applicationContext.xml配置文件中使用property标签注入。-->
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
    <property name="str" value="abc"/>
    <!--name:表示代码中的bean所要赋值的属性,更准确地说是setter方法方法名去掉set后首字母小写。-->
    <!--value:后面跟的是简单数据类型,对于参数类型,Spring在注入的时候会自动转换。-->
    <!--ref是指向Spring的Ioc容器中的另一个bean对象的,基本数据类型使用value属性。-->
    <property name="i" value="10"/>
</bean>

<3> 运行程序

public class App {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext cpxac = new ClassPathXmlApplicationContext("applicationContext.xml");
        BookDao bookDao = (BookDao) cpxac.getBean("bookDao");
        bookDao.save();
    }
}
//运行结果:BookDaoImpl_save,abc,10


3 构造器注入

//强制依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现。

(1) 注入引用数据类型

<1> 准备需要被创建的类,提供构造方法
//添加带有bookDao参数的构造方法

public class BookServiceImpl implements BookService{
    private BookDao bookDao;
    //构造方法
    public BookServiceImpl(BookDao bookDao) {
        this.bookDao = bookDao;
    }
    public void save() {
        System.out.println("BookServiceImpl_save");
        bookDao.save();
    }
}

<2> 配置文件中进行注入配置

<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
    <constructor-arg name="bookDao" ref="bookDao"/>
    <!--name属性对应的值为构造函数中方法形参的*参数名*,必须要保持一致。-->
    <!--ref属性指向的是spring的Ioc容器中其他bean对象。-->
</bean>

<3> 运行程序

public class App {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext cpxac = new ClassPathXmlApplicationContext("applicationContext.xml");
        BookService bookService = (BookService) cpxac.getBean("bookService");
        bookService.save();
    }
}
//运行结果:BookServiceImpl_save

(2) 注入简单数据类型

<1> 准备需要被创建的类,提供构造方法

public class BookDaoImpl implements BookDao {
    private String str;
    private int i;
    public BookDaoImpl(String str, int i) {
        this.str = str;
        this.i = i;
    }
    public void save() {
        System.out.println("BookDaoImpl,"+str+","+i);
    }
}

<2> 配置文件中进行注入配置

<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
    <constructor-arg name="str" value="abc"/>
    <constructor-arg name="i" value="10"/>
</bean>

<3> 运行程序

public class App {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext cpxac = new ClassPathXmlApplicationContext("applicationContext.xml");
        BookService bookService = (BookService) cpxac.getBean("bookService");
        bookService.save();
    }
}
//运行结果:BookDaoImpl,abc,10

(3) 进一步解耦(了解)

//当构造函数中方法的参数名发生变化后,配置文件中的name属性也需要跟着变。
<1> 删除name属性,添加type属性,按照类型注入

<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
    <constructor-arg type="java.lang.String" value="abc"/>
    //将abc注入到com.itheima.dao.impl.BookDaoImpl中java.lang.String的属性中。
    <constructor-arg type="int" value="10"/>
</bean>

//这种方式可以解决构造函数形参名发生变化带来的耦合问题,但是如果构造方法参数中有类型相同的参数,这种方式就会出现问题。
<2> 删除type属性,添加index属性,按照索引下标注入,下标从0开始

<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
    <constructor-arg index="1" value="abc"/>
    //将abc注入到com.itheima.dao.impl.BookDaoImpl中第一个属性中。
    <constructor-arg index="0" value="10"/>
</bean>

//这种方式可以解决参数类型重复问题,但是如果构造方法参数顺序发生变化后,这种方式又带来了耦合问题。

 

4 依赖自动装配

(1) 自动装配

IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配。

(2) 自动装配类型

<1> 按类型(常用)
<2> 按名称
<3> 按构造方法
<4> 不启用自动装配

(3) 自动装配配置

//前提:对应类中有setter方法,将类作为bean配置到配置文件。

<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" autowire="byType或者byName"/>
<!--autowire属性:开启自动装配,通常使用按类型装配。-->
<!--不需要写<property>标签。当需要使用某个类时,会自动在容器中通过类型和名字寻找该类。-->

(4) 注意事项

<1> 需要注入属性的类中对应属性的setter方法不能省略。
<2> 被注入的对象必须要被Spring的IOC容器管理。
<3> 按照类型在Spring的IOC容器中如果找到多个对象,会报 NoUniqueBeanDefinitionException
<4> 如果按照名称去找对应的bean对象,找不到则注入Null。

(5) 自动装配特征

<1> 自动装配用于引用类型依赖注入,不能对简单类型进行操作。
<2> 使用按类型装配时(byType)必须保障容器中相同类型的bean唯一,推荐使用。
<3> 使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用。
<4> 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效。

 

5 集合注入

//property标签表示setter方式注入,构造方式注入constructor-arg标签内部也可以写<array>、 <list>、 <set>、 <map>、 <props>标签。
//集合中要添加引用类型,只需要把<value>标签改成<ref>标签,这种方式用的比较少。

(1) 注入数组类型数据

<property name="a1">
    <array>
        <value>100</value>
        <value>200</value>
        <value>300</value>
    </array>
</property>

(2) 注入List类型数据

//List的底层也是通过数组实现的,所以<list><array>标签是可以混用。

<property name="l1">
    <list>
        <ref="bookDao"/>
        <value>abc</value>
        <value>abc</value>
        <value>abc</value>
        <value>abc</value>
    </list>
</property>

(3) 注入Set类型数据

<property name="s1">
    <set>
        <value>abc</value>
        <value>abc</value>
        <value>abc</value>
        <value>abc</value>
    </set>
</property>

(4) 注入Map类型数据

<property name="m1">
    <map>
        <entry key="country" value="china"/>
        <entry key="province" value="henan"/>
        <entry key="city" value="kaifeng"/>
    </map>
</property>

(5) 注入Properties类型数据

<property name="p1">
    <props>
        <prop key="country">china</prop>
        <prop key="province">henan</prop>
        <prop key="city">kaifeng</prop>
    </props>
</property>

 

posted @ 2023-10-17 10:53  10kcheung  阅读(25)  评论(0)    收藏  举报