依赖注入
(一)set注入
通过类setXxx()赋值
依赖注入底层是通过反射实现的。
<bean id="teacher" class="org.lanqiao.entity.teacher" >
<property name="name" value="java"></property>
</bean>
<bean id="course" class="org.lanqiao.entity.Course" >
<!-->8种基本数据类型和String用value<!-->
<property name="courseName" value="java"></property>
<property name="courseHour" value="200"></property>
<!-->对象用ref,实现依赖注入<!-->
<property name="teacher" ref="teacher"></property>
<!-->
XML预定义的实体引用
<property name="name" value="z<s"></property>
作用相同,但不加双引号
<property name="name" >
<value>java</value>
</property>
<property name="name" >
类型写全名
<value type="java.lang.String">z<![CDATA[<>&]]>s</value>
</property>
给对象类型赋值null,注意 没有<value> :
<property name="name" >
<null/>
</property>
赋空值 ""
<property name="name" >
<value></value>
</property>
<-->
</bean>
value与注入方式的区别:
使用子元素注入 | 而使用value属性注入 | |
---|---|---|
参数值位置 | 写在首尾标签()的中间(不加双引号) | 写在value的属性值中(必须加双引号) |
type属性 | 有(可选) 可以通过type属性指定数据类型 | 无 |
参数值包含特殊字符(<, &)时的处理方法 | 两种处理方法。 一、使用<![CDATA[]]> 标记 二、使用XML预定义的实体引用 | 一种处理方法。即使用XML预定义的实体引用 |
其中,XML预定义的实体引用,如表所示。
实体引用 | 表示的符号 |
---|---|
< | < |
& | & |
> | > |
(二)构造器注入
通过构造方法赋值
需要注意:如果 顺序 与构造方法参数的顺序不一致,则需要通过type或者index或name指定。
teacher.java
//构造器
public Teacher(String name, int age) {
this.name = name;
this.age = age;
}
xml
<bean id="teacher" class="org.lanqiao.entity.teacher" >
<!-->没有指定时赋值顺序应与构造器一致,否则报错<-->
<constructor-arg value="24" ></constructor-arg>
<constructor-arg value="ls" ></constructor-arg>
<!-->指定位置<-->
<constructor-arg value="24" index="1"></constructor-arg>
<constructor-arg value="ls" index="0"></constructor-arg>
<!-->指定变量<-->
<constructor-arg value="24" name="age"></constructor-arg>
<constructor-arg value="ls" name="name"></constructor-arg>
<!-->指定类型,默认匹配字符串,这样可以看出是什么类型<-->
<constructor-arg value="24" type="int" ></constructor-arg>
<constructor-arg value="ls" type="String" ></constructor-arg>
<!-->全部<-->
<constructor-arg value="24" type="int" index="1" name="age"></constructor-arg>
<constructor-arg value="ls" type="String" index="0" name="name"></constructor-arg>
</bean>
在ioc中定义bean的前提:该bean的类提供了 无参构造
(三)命名空间类注入
(1)引入p命名空间
xmlns:p="http://www.springframework.org/schema/p"
(2)xml
<bean id="teacher" class="org.lanqiao.entity.teacher" p:name="java">
</bean>
<bean id="course" class="org.lanqiao.entity.Course"
p:teacher-ref="teacher" p:courseHour="200" p:courseName="java" >
</bean>
简单类型:p:属性名=“属性值”
引用类型(除了String外):p:属性名-ref=“引用的id”
注意多个 p赋值的时候 要有空格。
无论是String还是Int/short/long,在赋值时都是 value=“值” ,因此建议 此种情况 需要配合 name\type进行区分
附:集合
<bean id="collectionDemo" class="org.lanqiao.entity.AllCollectionType" >
<!-- 通过set方式赋值
<property name="listElement">
<list>
<value>足球</value>
<value>篮球</value>
<value>乒乓球</value>
</list>
</property>
-->
<constructor-arg name="listElement">
<list>
<value>足球xx</value>
<value>篮球xx</value>
<value>乒乓球xxx</value>
</list>
</constructor-arg>
<property name="arrayElement">
<!-- <array>
<value>足球1</value>
<value>篮球1</value>
<value>乒乓球1</value>
</array>
-->
<!-->也可用list<-->
<list>
<value>足球1</value>
<value>篮球1</value>
<value>乒乓球1</value>
</list>
</property>
<property name="setElement">
<!-- <set>
<value>足球2</value>
<value>篮球1</value>
<value>乒乓球2</value>
</set>
-->
<!-->也可用list<-->
<list>
<value>足球2</value>
<value>篮球1</value>
<value>乒乓球2</value>
</list>
</property>
<property name="mapElement">
<map>
<entry>
<key>
<value>foot</value>
</key>
<value>足球3</value>
</entry>
<entry>
<key>
<value>basket</value>
</key>
<value>篮球3</value>
</entry>
<entry>
<key>
<value>pp3</value>
</key>
<value>乒乓球</value>
</entry>
</map>
</property>
<property name="propsElement">
<props>
<prop key="foot4">足球4</prop>
<prop key="basket4">篮球4</prop>
<prop key="pp4">乒乓球4</prop>
</props>
</property>
</bean>
(四)自动装配
<bean id="course" class="org.lanqiao.entity.Course" autowire="byName" >
<bean id="course" class="org.lanqiao.entity.Course" autowire="constructor" >
<bean id="course" class="org.lanqiao.entity.Course" autowire="byType" >
<property name="courseName" value="java"></property>
<property name="courseHour" value="200"></property>
<!-- <property name="teacher" ref="teacher"></property> -->
</bean>
byName: 自动寻找其他bean的id值=该Course类所有的的对象名。
byType: 自动寻找其他bean的类型(class) 是否与 该Course类所有的的对象属性一致 (此种方式必须满足当前Ioc容器中 只能有一个Bean满足条件 )。
constructor:自动寻找其他bean的类型(class) 是否与 该Course类的构造方法参数的类型一致;此种方式的本质就是byType。
可以在头文件中 一次性将该ioc容器的所有bean 统一设置成自动装配:
<beans xmlns="http://www.springframework.org/schema/beans"
...
default-autowire="byName">
自动装配虽然可以减少代码量,但是会降低程序的可读性,使用时需要谨慎。
(五)注解注入
xml
<!-- 配置扫描器 -->
<context:component-scan base-package="org.lanqiao.dao">
</context:component-scan>
org.lanqiao.dao包
//放入容器,相当于在xml中配置<bean id="studentDao" class="org.lanqiao.dao.StudentDaoImpl">
@Component("studentDao")
public class StudentDaoImpl {
public void addStudent(Student student) {
@Autowired//设置为自动装配,默认byType
@Qualifier("stuDao")//设置为byName,
//相当于在xml中配置<bean id="studentDao" class="org.lanqiao.dao.StudentDaoImpl"> <property name="studentDao" ref="stuDao"></property>
private IStudentDao studentDao;
System.out.println("...");
}
}
Spring在启动的时候,会根据base-package在 该包中扫描所有类,查找这些类是否有注解@Component(“studentDao”),如果有,则将该类 加入spring Ioc容器。
@Component细化:
dao层注解:@Repository
service层注解:@Service
控制器层注解:@Controller