6.依赖注入(Dependency Injection)
依赖:bean对象的创建依赖容器
注入:bean对象所有属性,由容器注入
6.1 构造函数注入
- 参考第四点创建对象的方式
- 构造函数注入分为
- 无参构造注入
- 有参构造注入
6.2 基于Setter的依赖注入(重点)
其实我们在一开始了解IOC思想的时候就是用Setter注入的但是那是最基本的下面开始分析复杂的
基于spring的setter注入官方解释
-
Spring团队通常提倡使用构造函数注入,因为它可以让您将应用程序组件实现为不可变对象,并确保不存在必需的依赖项
null
。此外,注入构造函数的组件始终以完全初始化的状态返回给客户端(调用)代码。附带说明一下,大量的构造函数自变量是一种不好的代码味,这表明该类可能承担了太多的职责,应进行重构以更好地解决关注点分离问题。 -
Setter注入主要应仅用于可以在类中分配合理的默认值的可选依赖项。否则,必须在代码使用依赖项的任何地方执行非空检查。
-
setter注入的一个好处是,setter方法可使该类的对象在以后重新配置或重新注入。
第一步:编写实体类(最好的各个注入类型都包含)(省略getset和toString)
public class Student implements Serializable {
private String name;
private Integer age;
private Teacher teacher;
private String[] books;
private List<String> hobbies;
private Map<String,Object> score;
private Set<String> games;
private Properties subject;
}
public class Teacher implements Serializable {
private String name;
private Integer age;
}
第二步:编写核心配置文件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="teacher" class="com.xuan.pojo.Teacher">
<constructor-arg type="java.lang.String" value="jiaoshi"/>
<constructor-arg type="java.lang.Integer" value="50"/>
</bean>
<bean id="student" class="com.xuan.pojo.Student">
<!--学生年龄-->
<property name="age" value="22"/>
<!--学生的姓名-->
<property name="name" value="xieying"/>
<!--引用老师类-->
<property name="teacher" ref="teacher"/>
<!--数组(书)-->
<property name="books">
<array>
<value>简爱</value>
<value>追风筝的人</value>
</array>
</property>
<!--list集合爱好-->
<property name="hobbies">
<list>
<value>打篮球</value>
<value>踢足球</value>
<value>打羽毛球</value>
</list>
</property>
<!--set集合(游戏)-->
<property name="games">
<set>
<value>王者荣耀</value>
<value>吃鸡</value>
<value>英雄联盟</value>
</set>
</property>
<!--map集合(分数)-->
<property name="score">
<map>
<entry key="语文" value="111"/>
<entry key="数学" value="96"/>
<entry key="英语" value="120"/>
</map>
</property>
<!--Properties集合(科目)-->
<property name="subject">
<props>
<prop key="chinese">yang</prop>
<prop key="English">huang</prop>
<prop key="sports">liu</prop>
</props>
</property>
</bean>
</beans>
第三步:编写测试
public class TestUser {
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
Student student = applicationContext.getBean("student", Student.class);
System.out.println(student);
}
}
测试结果:
Student{name='xieying', age=22, teacher=Student{name='jiaoshi', age=50},
books=[简爱, 追风筝的人], hobbies=[打篮球, 踢足球, 打羽毛球],
score={语文=111, 数学=96, 英语=120}, games=[王者荣耀, 吃鸡, 英雄联盟],
subject={English=huang, chinese=yang, sports=liu}}
6.3 拓展方式注入
6.3.1 p-命名空间的XML快捷方式(与set注入配合)
p-namespace允许您使用bean
元素的属性(而不是嵌套 <property/>
元素)来描述协作bean的属性值,或同时使用这两者。
-
Spring支持带有 XML定义的命名空间的可扩展配置格式。
-
xmlns:p="http://www.springframework.org/schema/p"
-
关键是引入相应的 p-命名空间
-
用法就是 P:属性=“属性值”
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 name="user" class="com.xuan.pojo.User" p:name="John" p:age="20"/>
</beans>
6.3.2 c-namespace的XML快捷方式(与构造器配合)
与p-namespace相识,c-namespace允许使用内联属性来配置构造函数参数,而不是嵌套constructor-arg
元素。
-
xmlns:c="http://www.springframework.org/schema/c"
-
引入c命名空间
-
用法: c:构造器参数=“属性值”
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<bean id="beanTwo" class="x.y.ThingTwo"/>
<bean id="beanThree" class="x.y.ThingThree"/>
<!-- traditional declaration with optional argument names -->
<bean id="beanOne" class="x.y.ThingOne">
<constructor-arg name="thingTwo" ref="beanTwo"/>
<constructor-arg name="thingThree" ref="beanThree"/>
<constructor-arg name="email" value="something@somewhere.com"/>
</bean>
<!-- c-namespace declaration with argument names -->
<bean id="beanOne" class="x.y.ThingOne" c:thingTwo-ref="beanTwo"
c:thingThree-ref="beanThree" c:email="something@somewhere.com"/>
</beans>