spring入门学习第二篇
依赖注入IOC
2004年,Martin Fowler探讨了同一个问题,既然IOC是控制反转,那么到底是“哪些方面的控制被反转了呢?”,经过详细地分析和论证后,他得出了答案:“获得依赖对象的过程被反转了”。控制被反转之后,获得依赖对象的过程由自身管理变为了由IOC容器主动注入。于是,他给“控制反转”取了一个更合适的名字叫做“依赖注入(Dependency Injection)”。他的这个答案,实际上给出了实现IOC的方法:注入。所谓依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。
依赖注入:spring管理的bean,当它依赖一个被其他spring管理的bean的时候,spring负责把它注入进来
注入方式
1、构造函数注入(Constructor)
2、属性注入(setter)
3、接口注入(比较少用)
案例一:
EmpDao接口:
package com.complex; public interface EmpDao { void insert(); }
EmpDaoImpl实现类:
package com.complex; public class EmpDaoImpl implements EmpDao{ @Override public void insert() { System.out.println("this is EmpDao Method insert"); } }
EmpService接口:
package com.complex; public interface EmpService { void insert(); }
EmpServiceImpl实现类:
package com.complex; public class EmpServiceImpl implements EmpService{ private EmpDao empDao; public EmpServiceImpl(){} //构造函数注入 public EmpServiceImpl(EmpDao empDao){ this.empDao = empDao;} @Override public void insert() { empDao.insert(); } }
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.xsd"> <bean id="empDaoImpl" class="com.complex.EmpDaoImpl"></bean> <bean id="empServiceImpl" class="com.complex.EmpServiceImpl"> <!--可以看到我们通过构造函数注入,实现了在实例化bean的时候会将empDaoImpl这个bean自动注入到empServiceImpl这个bean的构造函数中实例化bean--> <constructor-arg ref="empDaoImpl"></constructor-arg> </bean> </beans>
Main测试:
package com.complex;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext_complex.xml");
EmpServiceImpl empServiceImpl = context.getBean("empServiceImpl", EmpServiceImpl.class);
empServiceImpl.insert();
}
}
我们通过依赖注入实现了在实例化Bean的时候通过构造函数注入EmpDao
为什么EmpServiceImpl放EmpDao接口类型,因为这样遵循依赖倒转原则:抽象不应该依赖于细节,细节应该依赖于抽象。
1、如何实现多个属性通过构造器注入
BookInfo类
package com.basic;
import java.math.BigDecimal;
public class BookInfo {
private int id;
private String name;
private BigDecimal price;
private int count;
public BookInfo(int id, String name, BigDecimal price, int count) {
this.id = id;
this.name = name;
this.price = price;
this.count = count;
}
}
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.xsd"> <bean id="bookInfo" class="com.basic.BookInfo"> <constructor-arg name="id" value="1"></constructor-arg> <constructor-arg name="name" value="童话故事"></constructor-arg> <constructor-arg name="price" value="15"></constructor-arg> <constructor-arg name="count" value="100"></constructor-arg> </bean> </beans>
通过构造器注入我们可以指定构造参数,spring是如何知道要传的参数是哪个呢?
constructor-arg给我们提供了三种指定参数名的方法
name:设置参数名
index:设置参数索引
type:参数类型
如果不设置的话,spring会依据先后顺序一个个传参进去。
package com.basic; import java.math.BigDecimal; public class BookInfo { private int id; private String name; private BigDecimal price; private int count; //get和set方法,这里省略了 }
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.xsd"> <bean id="bookInfo" class="com.basic.BookInfo"> <property name="id" value="1"></property> <property name="name" value="童话故事"></property> <property name="price" value="15"></property> <property name="count" value="100"></property> </bean> </beans>
通过设置property实现属性注入,name指定对应的属性。
3、复杂类型如何注入?
前面我们实现的是简单的类型,那么问题来了,复杂类型如何注入?例如list,map,实体类等等
ShopCar
package com.basic; import java.util.List; import java.util.Map; import java.util.Set; public class ShopCar { private String sname; //基本类型 private List<BookInfo> list; //list集合 private Map<Integer,BookInfo> map; //map集合 private Set<BookInfo> bookInfoSet; //set集合 private BookInfo bookInfo; //实体对象 public ShopCar(String sname, List<BookInfo> list, Map<Integer, BookInfo> map, Set<BookInfo> bookInfoSet, BookInfo bookInfo) { this.sname = sname; this.list = list; this.map = map; this.bookInfoSet = bookInfoSet; this.bookInfo = bookInfo; } //set和get方法,这里省略了....太长了 }
先来看看构造函数注入复杂类型
<?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.xsd"> <bean id="bookInfo" class="com.basic.BookInfo"> <constructor-arg name="id" value="1"></constructor-arg> <constructor-arg name="name" value="童话故事"></constructor-arg> <constructor-arg name="price" value="15"></constructor-arg> <constructor-arg name="count" value="100"></constructor-arg> </bean> <bean id="shopCar" class="com.basic.ShopCar"> <!-- 普通类型一样用value--> <constructor-arg name="sname" value="购物车1"></constructor-arg> <!-- 实体类用ref--> <constructor-arg name="bookInfo" ref="bookInfo"></constructor-arg> <!-- list类型设置--> <constructor-arg name="list"> <list> <ref bean="bookInfo"></ref> <bean class="com.basic.BookInfo"> <property name="id" value="2"></property> <property name="name" value="小红帽"></property> <property name="price" value="15"></property> <property name="count" value="100"></property> </bean> </list> </constructor-arg> <!-- map设置--> <constructor-arg name="map"> <map> <entry key="1" value-ref="bookInfo"></entry> </map> </constructor-arg> <!-- set设置--> <constructor-arg name="bookInfoSet"> <set> <ref bean="bookInfo"></ref> </set> </constructor-arg> </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.xsd"> <bean id="bookInfo" class="com.basic.BookInfo"> <constructor-arg name="id" value="1"></constructor-arg> <constructor-arg name="name" value="童话故事"></constructor-arg> <constructor-arg name="price" value="15"></constructor-arg> <constructor-arg name="count" value="100"></constructor-arg> </bean> <bean id="shopCar" class="com.basic.ShopCar"> <!-- 基本类型--> <property name="sname" value="shop2"></property> <!-- 实体类型--> <property name="bookInfo" ref="bookInfo"></property> <!-- list类型--> <property name="list"> <list> <ref bean="bookInfo"></ref> </list> </property> <!-- map类型--> <property name="map"> <map> <entry key="1" value-ref="bookInfo"></entry> </map> </property> <!-- set类型--> <property name="bookInfoSet"> <set> <ref bean="bookInfo"></ref> </set> </property> </bean> </beans>
结束!