控制反转(IOC):说简单点就是实例化对象的控制权发生了转变,以前是我们自己new,现在交给Spring这个大工厂去实例化,如果我们现在要用对象,就直接向Spring这个大工厂索取就可以了.就像以前是自己做饭吃,现在是在餐馆点菜吃,只不过是点菜的方式有两种,一个set方式,一种构造器方式.
l 构造器方式注入
构造器参数类型匹配
要求构造参数非常明确,即参数列表不会有同类型的参数
以水果Service层为示例:
Service层需要持有Dao层对象,才能调用Dao层的方法.
服务层接口: public interface FruitService { public void create(); } 服务层实现类: public class FruitServiceImpl implements FruitService { private FruitDao fruitDao;
public FruitServiceImpl(FruitDao fruitDao) { super(); this.fruitDao = fruitDao; }
@Override public void create() { fruitDao.create(); } } 可以看到,和前面的set注入不同,提供的是我们熟悉的构造方法 |
配置文件:
<?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"> <constructor-arg type="dao.FruitDao" ref="fruitDao"/> </bean> </beans> |
Test:
public class Test {
public static void main(String[] args) { ApplicationContext acx = new ClassPathXmlApplicationContext( "chapter2.xml"); FruitService fruitService = (FruitService) acx .getBean("fruitService"); fruitService.create(); } } |
构造参数索引
可以解决参数同类型问题,并且配置时不用去维护参数顺序的问题,如果使用构造器注入(推荐使用这种方式),或者将前两者结合起来一起使用.
给服务层添加了两个字符串属性name, address, 注意这里只是为了演示方便
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; }
@Override 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; } } |
配置:
第一种方式:
<?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"> <constructor-arg index="0" ref="fruitDao" /> <constructor-arg index="1" value="wdpc" /> <constructor-arg index="2" value="武大" /> </bean> </beans> |
第二种方式:
<?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"> <constructor-arg index="0" type="dao.FruitDao" ref="fruitDao" /> <constructor-arg index="1" type="java.lang.String" value="wdpc" /> <constructor-arg index="2" type="java.lang.String" value="武大" /> </bean> </beans> |
Test:
public class Test {
public static void main(String[] args) { ApplicationContext acx = new ClassPathXmlApplicationContext( "chapter2.xml"); FruitService fruitService = (FruitService) acx .getBean("fruitService"); fruitService.create(); System.out.println(((FruitServiceImpl)fruitService).getName()); System.out.println(((FruitServiceImpl)fruitService).getAddress()); } } |
(FruitServiceImpl)fruitService)注意这一句,因为fruitService是服务层的接口,接口中只暴露了一个create方法,所以我们只能调用create方法,如果想调用其它的get方法,就需要将接口强转为实现类,注意这一点,这也是使用接口的一个好处,只暴露接口中定义的方法,
l 集合的注入
1. set
2. list
3. properties
4. map
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> mpas = 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> getMpas() { return mpas; }
public void setMpas(Map<String, String> mpas) { this.mpas = mpas; } }
|
配置:
<?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="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="pkey1">pkey1</prop> <prop key="pkey2">pkey2</prop> <prop key="pkey3">pkey3</prop> </props> </property> <property name="mpas"> <map> <entry key="mkey1" value="mkey1" /> <entry key="mkey2" value="mkey2" /> <entry key="mkey3" value="mkey3" /> </map> </property> </bean> </beans> |
Test:
public class Test {
public static void main(String[] args) { ApplicationContext acx = new ClassPathXmlApplicationContext( "chapter2.xml"); CollectionService collectionService = (CollectionService) acx .getBean("collectionService"); Set<String> set = collectionService.getSets(); for (String s : set) { System.out.println(s); } System.out.println("========================"); List<String> lists = collectionService.getLists(); for (String s : lists) { System.out.println(s); } System.out.println("========================"); Properties properties = collectionService.getProperties(); for (Object key : properties.keySet()) { System.out .println(key + ":" + properties.getProperty((String) key)); } System.out.println("========================"); Map<String, String> mpas = collectionService.getMpas(); for(String key : mpas.keySet()){ System.out .println(key + ":" + mpas.get((String) key)); } } } |
l 自动装配
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的属性.
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类型即可.
尽量不要用自动装配的特性,因为会产生二异性,特别是按类型装配,