控制反转 Inversion of Control
Spring 控制反转容器的使用
通过构造器创建一个 bean 实例
<!-- spring-config.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 name="product" class="app15a.bean.Product" /> <!-- 注意应采用 id 或者 name 属性标识一个 bean --> </beans>
该 bean 的定义告诉 Spring 通过默认的无参构造器来初始化 Product 类,如果不存在无参构造器,则 Spring 将抛出一个异常。
为了让 Spring 创建一个 Product 实例,应将 bean 定义的 name 值(或者 id 值)和 Product 类型作为参数传递给 ApplicationContext 的 getBean 方法:
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"spring-config.xml"}); // 导入配置文件 Product product1 = context.getBean("product", Product.class); // 让 Spring 创建一个 Product 实例 product1.setName("Excellent snake oil"); // 给 product 的 name 属性赋值 System.out.println("product1: " + product1.getName()); // 获取 product 的 name 属性
通过工厂方法创建一个 bean 实例
<!-- spring-config.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="calendar" class="java.util.Calendar" factory-method="getInstance" /> </beans>
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"spring-config.xml"}); // 导入配置文件 Product product1 = context.getBean("calendar", Calendar.class); // 让 Spring 创建一个 Calendar 实例
Destroy Method 的使用
可以在 bean 定义中配置 destroy-method 属性,用来指定在销毁前要被执行的方法。
在该例子中,配置 Spring 通过 java.util.concurrent.Executors 的静态方法 newCachedThreadPool 创建一个 java.util.concurrent.ExecutorService 实例,并指定了 destroy-method 属性值为 shutdown 方法,这样,Spring 会在销毁 ExecutorService 实例前调用其 shutdown 方法。
<!-- spring-config.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="executorService" class="java.util.concurrent.Executors" factory-method="newCachedThreadPool" destroy-method="shutdown" /> </beans>
向构造器传递参数
package app15a.bean; import java.io.Serializable; public class Product implements Serializable { private static final long serialVersionUID = 748392348L; private String name; private String description; private float price; public Product() { // 无参构造器 } public Product(String name, String description, float price) { // 有参构造器 this.name = name; this.description = description; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public float getPrice() { return price; } public void setPrice(float price) { this.price = price; } }
配置文件 spring-config.xml
<!-- spring-config.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 name="featuredProduct" class="app15a.bean.Product" > <constructor-arg name="name" value="Ultimate Olive Oil" /> <!-- 通过参数名向构造函数传递参数 --> <constructor-arg name="description" value="The purest olive on the market" /> <constructor-arg name="price" value="9.95" /> </bean> </beans>
这样,在创建 Product 实例时,Spring 会调用以下构造器
public Product(String name, String description, float price) { // 有参构造器 this.name = name; this.description = description; this.price = price; }
setter方式依赖注入
package app15a.bean; public class Address { private String line1; private String line2; private String city; private String state; private String zipCode; private String country; public Address(String line1, String line2, String city, String state, String zipCode, String country) { this.line1 = line1; this.line2 = line2; this.city = city; this.state = state; this.zipCode = zipCode; this.country = country; } public String getLine1() { return line1; } public void setLine1(String line1) { this.line1 = line1; } public String getLine2() { return line2; } public void setLine2(String line2) { this.line2 = line2; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getState() { return state; } public void setState(String state) { this.state = state; } public String getZipCode() { return zipCode; } public void setZipCode(String zipCode) { this.zipCode = zipCode; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } @Override public String toString() { return line1 + "\n" + line2 + "\n" + city + "\n" + state + " " + zipCode + "\n" + country; } } ////////////////////////////// package app15a.bean; public class Employee { private String firstName; private String lastName; private Address homeAddress; public Employee() { } public Employee(String firstName, String lastName, Address homeAddress) { this.firstName = firstName; this.lastName = lastName; this.homeAddress = homeAddress; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public Address getHomeAddress() { return homeAddress; } public void setHomeAddress(Address homeAddress) { this.homeAddress = homeAddress; } @Override public String toString() { return firstName + " " + lastName + "\n" + homeAddress; } }
配置文件 spring-config.xml
<!-- spring-config.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 name="simpleAddress" class="app15a.bean.Address" > <!-- 通过构造方法传递参数 --> <constructor-arg name="line1" value="151 Corner Street" /> <constructor-arg name="line2" value="" /> <constructor-arg name="city" value="Albany" /> <constructor-arg name="state" value="NY" /> <constructor-arg name="zipCode" value="99999" /> <constructor-arg name="country" value="US" /> </bean> <bean name="employ2" class="app15a.bean.Employee"> <!-- setter方式依赖注入 --> <property name="homeAddress" ref="simpleAddress" /> <property name="firstName" value="Junior" /> <property name="lastName" value="Moore" /> </bean> </beans>
simpleAddress 对象是 Address 类的一个实例,其通过构造器方式实例化;employ1 对象则通过配置 property 元素来调用 setter 方法来设置值。
homeAddress 属性配置的是 simpleAddress 对象的引用。
构造器方式依赖注入
<!-- spring-config.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 name="employ2" class="app15a.bean.Employee"> <!-- 构造器方式依赖注入 --> <constructor-arg name="firstName" ref="Senior" /> <constructor-arg name="lastName" value="Moore" /> <constructor-arg name="homeAddress" value="simpleAddress" /> </bean> <bean name="simpleAddress" class="app15a.bean.Address" > <!-- 通过构造方法传递参数 --> <constructor-arg name="line1" value="151 Corner Street" /> <constructor-arg name="line2" value="" /> <constructor-arg name="city" value="Albany" /> <constructor-arg name="state" value="NY" /> <constructor-arg name="zipCode" value="99999" /> <constructor-arg name="country" value="US" /> </bean> </beans>