当一个类A作为类B的属性,如何实例化类A:
主动创建:
public class catService {
//注入方式1:new对象
catDao cd=new catDao();
}
非主动创建:
public class catService {
//注入方式2:参数传入
private catDao cd;
public catService(catDao catDao){
this.cd=catDao;
}
}
对比第二种方式,并没有像第一种方式一样创建对象,而是通过带参方法的形式传入一个对象,从而实现依赖,而实际的对象创建交给了外部。
1:set注入(首选)
前提:需要提供属性的set方法
a:bean对象的注入
public class userDao {
public void userDaoMethod(){
System.out.println("userDaoMethod");
}
}
public class userService {
private dao.userDao userDao;
//set方法注入业务对象
public void setUserDao(dao.userDao userDao) {
this.userDao = userDao;
}
public void userServiceMethod(){
this.userDao.userDaoMethod();
}
}
<!--
IOC通过property标签手动装配(注入)
Set方法注入:
name:bean对象中的属性名
ref:指定bean标签的id属性值,将实例化好的userDao传给set方法
-->
<bean id="userDao" class="dao.userDao"></bean>
<bean id="userService" class="service.userService">
<property name="userDao" ref="userDao"></property>
</bean>
b:基本引用和基本数据类型
<!--String-->
<property name="host" value="localHost"></property>
<!--Integer-->
<property name="port" value="8080"></property>
<!--list-->
<property name="list">
<list>
<value>上海</value>
<value>北京</value>
</list>
</property>
<!--map-->
<property name="map">
<map>
<entry>
<key><value>1</value></key>
<value>一号</value>
</entry>
<entry>
<key><value>2</value></key>
<value>二号</value>
</entry>
</map>
</property>
<!--properties-->
<property name="properties">
<props>
<prop key="jdbc.driver">com.mysql.jdbc.Driver</prop>
</props>
</property>
P名称空间:
xmlns:p="http://www.springframework.org/schema/p"
便于set注入的使用:
<!--set注入使用P名称空间-->
<bean id="pDap" class="dao.pDao"></bean>
<bean id="pService" class="service.pService" p:pd-ref="pDap" p:str="p名称空间">
</bean>
2:构造器注入
前提:提供带参的构造器
catDao作为catService的属性:
public class catService {
private catDao cd;
//提供带参构造
public catService(catDao cd){
this.cd=cd;
}
public void catServiceMethod(){
System.out.println("catServiceMethod");
this.cd.catDaoMethod();
}
}
public class catDao {
public void catDaoMethod(){
System.out.println("catDaoMethod");
}
}
spring.xml:
<!--
SpringIOC手动装配(注入):
构造器注入:
constructor-arg标签进行注入
name:对应形参名
ref:指定bean标签的id属性值
value:值
index:参数下标 从0开始
-->
<bean id="catDao" class="dao.catDao"></bean>
<bean id="catService" class="service.catService">
<constructor-arg name="cd" ref="catDao"></constructor-arg>
</bean>
如果存在多个bena属性:
<bean id="catService" class="service.catService">
<constructor-arg name="cd" ref="catDao"></constructor-arg>
<constructor-arg name="ud" ref="userDao"></constructor-arg>
</bean>
构造器注入的问题:
如果A依赖B,B依赖A,都是构造器注入,则会引起循环依赖,通过set注入则会避免循环依赖。因为set注入在实例化对象时不需要注入属性,只有在使用时才会去注入属性。
3:静态工厂注入
静态工厂注入的本质:
利用set注入被静态工厂实例化的bean。
前提:set方法
TypeDao作为TypeService的属性:
//DAO
public class TypeDao {
public void TypeDaoTest(){
System.out.println("TypeDaoTest");
}
}
//Service
public class TypeService {
private TypeDao td;
public void setTd(TypeDao td) {
this.td = td;
}
public void TypeServiceTest(){
System.out.println("TypeServiceTest");
}
}
静态工厂类:
//factory
public class StaticFactory {
//定义静态方法
public static TypeDao createTypeDao(){
return new TypeDao();
}
}
spring.xml:
<!--
静态工厂注入:
静态工厂注入也是借助set注入,被注入的bean对象是静态工厂实例化的
-->
<!--静态工厂实例化-->
<bean id="typeDao" class="factory.StaticFactory" factory-method="createTypeDao"></bean>
<!--引用静态工厂实例化的bean进行注入-->
<bean id="typeService" class="service.TypeService">
<property name="td" ref="typeDao"></property>
</bean>
4:实例化工厂注入
实例化工厂注入的本质:
注入被实例化工厂实例的bean对象
实例化工厂类:
//实例化工厂
public class dynamicFactory {
public TypeDao createTD(){
return new TypeDao();
}
}
spring.xml:
<!--
实例化工厂注入:
实例化工厂注入,借助set注入被实例化工厂 实例化的bean对象
-->
<!--实例化工厂bean-->
<bean id="dynamicFactory" class="factory.dynamicFactory"></bean>
<!--通过实例化工厂 实例bean-->
<bean id="typeDao" factory-bean="dynamicFactory" factory-method="createTD"></bean>
<!--将通过实例化工厂 实例的bean 利用set注入-->
<bean id="typeService" class="service.TypeService">
<property name="td" ref="typeDdao"></property>
</bean>