第四章 构造器注入,自动装配,集合注入
一:控制反转(IOC):就是实例化对象的控制权发生了转变,以前是我们自己new,现在交给spring这个工厂去实例化,如果我现在要用对象,就直接向spring这个工厂索取就可以了。
两种方式:set方式和构造器方式。
二:构造器方式注入
构造器参数类型的匹配
要求构造参数非常明确,即参数列表不会有同类型的参数。
以水果service层为例:
service层需要持有Dao层对象,才能调用Dao层方法。
//Dao层接口:
package com.spring.chapter4.dao; public interface FruitDao { public void create(); }
//Dao层实现类:
package com.spring.chapter4.dao.impl; import com.spring.chapter4.dao.FruitDao; public class FruitDaoImpl implements FruitDao { public void create() { System.out.println("Dao层方法create被调用"); } }
//服务层接口:
package com.spring.chapter4.service; public interface FruitService { public void create(); }
//服务层实现类:
package com.spring.chapter4.service.impl; import com.spring.chapter4.dao.FruitDao; import com.spring.chapter4.service.FruitService; public class FruitServiceImpl implements FruitService { private FruitDao fruitDao; public FruitServiceImpl(FruitDao fruitDao) { super(); this.fruitDao = fruitDao; } public void create() { fruitDao.create(); } }
这里和我们前面set注入的不同,提供的时我们熟悉的构造方法。
//配置文件(chapter4.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 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="fruitDao" class="com.spring.chapter4.dao.impl.FruitDaoImpl"/> <bean id="fruitService" class="com.spring.chapter4.service.impl.FruitServiceImpl"> <constructor-arg type="com.spring.chapter4.dao.FruitDao" ref="fruitDao"/> </bean> </beans>
//测试类
package com.spring.chapter4.service.impl; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.spring.chapter4.service.FruitService; public class Test { public static void main(String[] args) { ApplicationContext act = new ClassPathXmlApplicationContext( "chapter4.xml"); FruitService fruitService = (FruitService) act.getBean("fruitService"); fruitService.create(); } }
三:构造参数索引:
可以解决参数同类型问题,并且配置时不用去维护参数顺序的问题,如果使用构造器注入(推荐使用这种方式),或者将前两者结合起来一起使用。
例如:给服务层添加两个属性
package com.spring.chapter4.service.impl; import com.spring.chapter4.dao.FruitDao; import com.spring.chapter4.service.FruitService; public class FruitServiceImpl implements FruitService { private FruitDao fruitDao; private String name; private String address; public FruitServiceImpl(FruitDao fruitDao) { super(); this.fruitDao = fruitDao; } public FruitServiceImpl(FruitDao fruitDao, String name, String address) { super(); this.fruitDao = fruitDao; this.name = name; this.address = address; } public void create() { fruitDao.create(); } public FruitDao getFruitDao() { return fruitDao; } public void setFruitDao(FruitDao fruitDao) { this.fruitDao = fruitDao; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
//配置文件(chapter4.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 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="fruitDao" class="com.spring.chapter4.dao.impl.FruitDaoImpl"/> <bean id="fruitService" class="com.spring.chapter4.service.impl.FruitServiceImpl"> <constructor-arg index="0" ref="fruitDao" /> <constructor-arg index="1" value="桔子" /> <constructor-arg index="2" value="中国" /> </bean> </beans>
//测试类:
package com.spring.chapter4.service.impl; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.spring.chapter4.service.FruitService; public class Test { public static void main(String[] args) { ApplicationContext act = new ClassPathXmlApplicationContext("chapter4.xml"); FruitService fruitService = (FruitService) act.getBean("fruitService"); fruitService.create(); System.out.println(((FruitServiceImpl)fruitService).getName()); System.out.println(((FruitServiceImpl)fruitService).getAddress()); } }
四:集合注入
Set集合、list集合、properties集合、map集合
package com.spring.chapter4.service.impl; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; public class CollectionService { private Set<String> sets = new HashSet<String>(); private List<String> lists = new ArrayList<String>(); private Properties properties = new Properties(); private Map<String,String> maps = new HashMap<String, String>(); public Set<String> getSets() { return sets; } public void setSets(Set<String> sets) { this.sets = sets; } public List<String> getLists() { return lists; } public void setLists(List<String> lists) { this.lists = lists; } public Properties getProperties() { return properties; } public void setProperties(Properties properties) { this.properties = properties; } public Map<String, String> getMaps() { return maps; } public void setMaps(Map<String, String> maps) { this.maps = maps; } }
//配置文件(collection.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 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="collectionService" class="com.spring.chapter4.service.impl.CollectionService"> <property name="sets"> <set> <value>set1</value> <value>set2</value> <value>set3</value> </set> </property> <property name="lists"> <list> <value>list1</value> <value>list2</value> <value>list3</value> </list> </property> <property name="properties"> <props> <prop key="key1">properties1</prop> <prop key="key2">properties2</prop> <prop key="key3">properties3</prop> </props> </property> <property name="maps"> <map> <entry key="key1" value="maps1"/> <entry key="key2" value="maps2"/> <entry key="key3" value="maps3"/> </map> </property> </bean> </beans>
//测试类:
package com.spring.chapter4.service.impl; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestDemo { public static void main(String[] args) { ApplicationContext act = new ClassPathXmlApplicationContext("collection.xml"); CollectionService collectionService = (CollectionService) act.getBean("collectionService"); Set<String> set = collectionService.getSets(); for(String s:set){ System.out.println(s); } List<String> lists = collectionService.getLists(); for (String s : lists) { System.out.println(s); } Properties properties = collectionService.getProperties(); for (Object key : properties.keySet()) { System.out.println(key + ":" + properties.getProperty((String) key)); } Map<String, String> mpas = collectionService.getMaps(); for(String key : mpas.keySet()){ System.out.println(key + ":" + mpas.get((String) key)); } } }
五:自动装配
(1). byName
<?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 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="fruitDao" class="dao.impl.FruitDaoImpl" /> <bean id="fruitService" class="service.impl.FruitServiceImpl" autowire="byName" /> </beans>
需要注意的地方: <bean id="fruitDao" class="dao.impl.FruitDaoImpl" />id="fruitDao"一定要和服务层的属性名称对应,即FruitDaoImpl类里面一定要有一个名称为fruitDao的属性.
(2). byType
<?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 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="fruitDao" class="dao.impl.FruitDaoImpl" /> <bean id="fruitService" class="service.impl.FruitServiceImpl" autowire="byType" /> </beans>
需要保证FruitServiceImpl类中有一个属性类型是FruitDao类型即可.
尽量不要用自动装配的特性,因为会产生二异性,特别是按类型装配