Spring学习笔记——第四部分 Dependency Injection(依赖注入):基于xml的注入
1. 前言
- 依赖注入(DI)与控制反转(IoC)含义相同,它们从两个角度描述同一概念。
- 当某个java对象要调用另一个java对象时,在传统模式下,我们会使用new来创建对象。
这种方式会导致调用者和被调用者之间的耦合性增加(我们应当实现低耦合),不利于后期的升级与维护。 - 而在Spring框架中,对象的实例化不需要由调用者实现,而由Spring容器来实现,由Spring容器来控制程序之间的关系,控制权由应用代码转移到Spring容器,此即:控制反转。
- 从容器的角度来看,它把被依赖对象赋值给调用对象,这相当于给调用对象注入了该对象依赖的实例,此即:依赖注入。、
- Spring提供了两种基于xml的注入方式:构造器注入、setter方法注入
2. Constructor-based Dependency Injection(构造器注入)
-
在使用构造器注入时,在配置文件里,需要使用
<bean>
元素的子元素<constructor-arg>
来定义构造方法的参数。 -
在使用构造器注入时,需要类提供有所有参数的有参构造方法。
<!--第一种:下标赋值-->
<bean id="user" class="com.zhang.pojo.User">
<constructor-arg index="0" value="张作鹏1"/>
</bean>
<!--第二种:通过类型创建,不建议使用-->
<bean id="user" class="com.zhang.pojo.User">
<constructor-arg type="java.lang.String" value="张作鹏2"/>
</bean>
<!--第三种:直接通过参数名-->
<bean id="user" class="com.zhang.pojo.User">
<constructor-arg name="name" value="张作鹏3"/>
</bean>
总结:在配置文件加载的时候,容器中管理的对象就已经初始化了。
3. Setter-based Dependency Injection(setter方法注入)【重点】
- 在Spring实例化Bean的过程中,Spring首先调用Bean的默认构造方法来实例化Bean,然后通过反射的方式调用setter方法注入属性值。
- 由于上述原因,在使用setter方法注入时,需要提供默认无参构造方法,以及所有属性的setter方法。
- 复杂类型(部分代码)
public class Address {
private String address;
}
- 真实测试对象(部分代码)
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbies;
private Map<String,String> card;
private Set<String> games;
private Properties info;
private String wife;
}
- applicationContext.xml
<?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="TYUTstudent" class="com.zhang.pojo.Student">
<!--第一种:普通值注入,value-->
<property name="name" value="TYUT张作鹏"/>
</bean>
</beans>
- 测试类
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Student student = (Student) context.getBean("TYUTstudent");
System.out.println(student.getName());
}
- 完善注入信息
<?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="address" class="com.zhang.pojo.Address"/>
<bean id="TYUTstudent" class="com.zhang.pojo.Student">
<!--普通值注入,value-->
<property name="name" value="TYUT张作鹏"/>
<!--bean注入,ref-->
<property name="address" ref="address"/>
<!--数组-->
<property name="books">
<array>
<value>《java学习》</value>
<value>《python学习》</value>
<value>《spring学习》</value>
</array>
</property>
<!--List-->
<property name="hobbies">
<list>
<value>写代码</value>
<value>吃东西</value>
</list>
</property>
<!--Map-->
<property name="card">
<map>
<entry key="身份证" value="140729"/>
<entry key="银行卡" value="132546"/>
</map>
</property>
<!--set-->
<property name="games">
<set>
<value>LOL</value>
<value>连连看</value>
</set>
</property>
<!--null-->
<property name="wife">
<null/>
</property>
<!--properties-->
<property name="info">
<props>
<prop key="学号">2018005624</prop>
<prop key="性别">男</prop>
</props>
</property>
</bean>
</beans>
4. 拓展方式注入
4.1 p-namespace and c-namespace(p命名空间与c命名空间)
<?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"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--p命名空间注入,可以直接注入属性的值:property-->
<bean id="user" class="com.zhang.pojo.User" p:name="P张作鹏" p:age="18"/>
<!--c命名空间注入,通过构造器注入:constructs-->
<bean id="user2" class="com.zhang.pojo.User" c:name="C张作鹏" c:age="18"/>
</beans>
4.2 注意点
两个命名空间不能直接使用,必须导入xml约束。
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"