Spring 支持 4 种依赖注入的方式
属性注入
构造器注入
工厂方法注入(静态工厂方法、实例工厂方法)
FactoryBean
属性注入
属性注入即通过 setter 方法注入Bean 的属性值或依赖的对象
属性注入使用 <property> 元素, 使用 name 属性指定 Bean 的属性名称,value 属性或 <value> 子节点指定属性值
属性注入是实际应用中最常用的注入方式
<!--配置一个 bean-->
<bean id="department1" class="xyz.huning.spring4.di.Department">
<!--属性注入-->
<property name="id">
<value>1</value>
</property>
<property name="name">
<value>Newton</value>
</property>
</bean>
构造器注入
通过构造方法注入Bean 的属性值或依赖的对象,它保证了 Bean 实例在实例化后就可以使用。
构造器注入在 <constructor-arg> 元素里声明属性, <constructor-arg> 中没有 name 属性
按索引匹配入参:
<!--配置一个 bean-->
<!-- 若一个 bean 有多个构造器, 如何通过构造器来为 bean 的属性赋值 -->
<!-- 可以根据 index 和 value 进行更加精确的定位.-->
<bean id="employee2" class="xyz.huning.spring4.di.Employee">
<!--构造器注入-->
<!-- 要求: 在 Bean 中必须有对应的构造器.-->
<!--按索引匹配入参-->
<constructor-arg value="2" index="0"></constructor-arg>
<constructor-arg value="huning" index="1"></constructor-arg>
<constructor-arg value="male" index="2"></constructor-arg>
</bean>
按类型匹配入参:
<!--配置一个 bean-->
<bean id="employee3" class="xyz.huning.spring4.di.Employee">
<!--构造器注入-->
<!--按类型匹配入参-->
<constructor-arg value="3" type="int"></constructor-arg>
<constructor-arg value="yingzi" type="java.lang.String"></constructor-arg>
<constructor-arg ref="department1" type="xyz.huning.spring4.di.Department"></constructor-arg>
</bean>
字面量
字面值:可用字符串表示的值,可以通过 <value> 元素标签或 value 属性进行注入。
基本数据类型及其封装类、String 等类型都可以采取字面值注入的方式
若字面值中包含特殊字符,可以使用 <![CDATA[]]> 把字面值包裹起来。
<!--配置一个 bean-->
<bean id="department2" class="xyz.huning.spring4.di.Department">
<property name="id" value="2"></property>
<!--若字面值中包含特殊字符, 则可以使用 DCDATA 来进行赋值.-->
<property name="name">
<value><![CDATA[<Newton>]]></value>
</property>
</bean>
引用其它 Bean
组成应用程序的 Bean 经常需要相互协作以完成应用程序的功能. 要使 Bean 能够相互访问, 就必须在 Bean 配置文件中指定对 Bean 的引用
在 Bean 的配置文件中, 可以通过 <ref> 元素或 ref 属性为 Bean 的属性或构造器参数指定对 Bean 的引用.
也可以在属性或构造器里包含 Bean 的声明, 这样的 Bean 称为内部 Bean
<!--配置一个 bean-->
<bean id="employee1" class="xyz.huning.spring4.di.Employee">
<!--属性注入-->
<!-- 通过属性注入: 通过 set方法注入属性值 -->
<property name="id" value="1"></property>
<!--通过 ref属性值指定当前属性指向哪一个bean-->
<property name="department" ref="department1"></property>
</bean>
内部 Bean
当 Bean 实例仅仅给一个特定的属性使用时, 可以将其声明为内部 Bean. 内部 Bean 声明直接包含在 <property> 或 <constructor-arg> 元素里, 不需要设置任何 id 或 name 属性
内部 Bean 不能使用在任何其他地方
<!--配置一个 bean-->
<bean id="employee4" class="xyz.huning.spring4.di.Employee">
<property name="id" value="4"></property>
<property name="department">
<!-- 内部 bean, 类似于匿名内部类对象. 不能被外部的 bean 来引用, 也没有必要设置 id 属性 -->
<bean class="xyz.huning.spring4.di.Department">
<property name="id" value="3"></property>
<property name="name" value="Gaussian"></property>
</bean>
</property>
</bean>
注入参数详解:null 值和级联属性
可以使用专用的 <null/> 元素标签为 Bean 的字符串或其它对象类型的属性注入 null 值
和 Struts、Hiberante 等框架一样,Spring 支持级联属性的配置。
<!--配置一个 bean-->
<bean id="employee5" class="xyz.huning.spring4.di.Employee">
<property name="id" value="5"></property>
<!--使用专用的 <null/> 元素标签为 Bean 的字符串或其它对象类型的属性注入 null 值-->
<property name="department"><null/></property>
</bean>
Java代码
package xyz.huning.spring4.di;
public class Department {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Department [id=" + id + ", name=" + name + "]";
}
}
package xyz.huning.spring4.di;
public class Employee {
private int id;
private String name;
private String gender;
private Department department;
public Employee() {
}
public Employee(int id, String name, String gender) {
this.id = id;
this.name = name;
this.gender = gender;
}
public Employee(int id, String name, Department department) {
this.id = id;
this.name = name;
this.department = department;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", gender=" + gender
+ ", department=" + department + "]";
}
}
package xyz.huning.spring4.di;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("di.xml");
Employee employee1 = context.getBean("employee1", Employee.class);
System.out.println(employee1);
Employee employee2 = context.getBean("employee2", Employee.class);
System.out.println(employee2);
Employee employee3 = context.getBean("employee3", Employee.class);
System.out.println(employee3);
Employee employee4 = context.getBean("employee4", Employee.class);
System.out.println(employee4);
Department department2 = context.getBean("department2", Department.class);
System.out.println(department2);
Employee employee5 = context.getBean("employee5", Employee.class);
System.out.println(employee5);
Employee employee6 = context.getBean("employee6", Employee.class);
System.out.println(employee6);
}
}
静态工厂方法&实例工厂方法
添加类模型:
package xyz.huning.spring4.factorymethod;
public class Car {
private int id;
private String brand;
private double price;
public Car()
{
}
public Car(int id,String brand,double price)
{
this.id = id;
this.brand = brand;
this.price = price;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Car [id=" + id + ", brand=" + brand + ", price=" + price + "]";
}
}
package xyz.huning.spring4.factorymethod;
import java.util.HashMap;
import java.util.Map;
/**
*
* 静态工厂方法:直接调用某个类的静态方法就可以返回bean实例
*/
public class StaticCarFactory {
private static Map<Integer,Car> cache = new HashMap<Integer,Car>();
static{
Car car1 = new Car(1,"QQ",50000);
Car car2 = new Car(2,"BMW",200000);
cache.put(car1.getId(), car1);
cache.put(car2.getId(), car2);
}
//静态工厂方法
public static Car getCar(int id)
{
return cache.get(id);
}
}
package xyz.huning.spring4.factorymethod;
import java.util.HashMap;
import java.util.Map;
/**
* 实例工厂方法:需要先创建共产本身,在调用工厂的实例方法来返回bean的实例
*
* @author Administrator
*
*/
public class InstanceCarFactory {
private Map<Integer,Car> cache = new HashMap<Integer,Car>();
public InstanceCarFactory()
{
Car car1 = new Car(1,"QQ",50000);
Car car2 = new Car(2,"BMW",200000);
this.cache.put(car1.getId(), car1);
this.cache.put(car2.getId(), car2);
}
public Car getCar(int id)
{
return this.cache.get(id);
}
}
添加配置:
<?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->
<!--通过静态工厂方法来配置bean.注意不是配置静态工厂方法实例.而是配置bean实例-->
<!--
class 属性:指向静态工厂方法的全类名
factory-method:指向静态工厂方法的名字
constructor-arg:如果工厂方法需要传入参数,则使用constructor-arg来配置参数
-->
<bean id="car1" class="xyz.huning.spring4.factorymethod.StaticCarFactory"
factory-method="getCar">
<constructor-arg name="id" value="1"></constructor-arg>
</bean>
<!--实例工厂方法配置bean->
<!--配置工厂的实例-->
<bean id="instanceCarFactory" class="xyz.huning.spring4.factorymethod.InstanceCarFactory"></bean>
<!--通过实例工厂方法来配置bean-->
<!--
factory-bean: 属性:指向工厂的实例
factory-method:指向实例工厂方法的名字
constructor-arg:如果工厂方法需要传入参数,则使用constructor-arg来配置参数
-->
<bean id="car2" factory-bean="instanceCarFactory" factory-method="getCar">
<constructor-arg name="id" value="2"></constructor-arg>
</bean>
</beans>
添加测试类:
package xyz.huning.spring4.factorymethod;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("factorymethod.xml");
Car car1 = context.getBean("car1", Car.class);
System.out.println(car1);
Car car2 = context.getBean("car2", Car.class);
System.out.println(car2);
((ClassPathXmlApplicationContext)context).close();
}
}
FactoryBean
添加类模型:
package xyz.huning.spring4.factorybean;
public class Airplane {
private int id;
private String type;
public Airplane()
{}
public Airplane(int id,String type)
{
this.id = id;
this.type = type;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
return "Airplane [id=" + id + ", type=" + type + "]";
}
}
package xyz.huning.spring4.factorybean;
import org.springframework.beans.factory.FactoryBean;
/**
*
* 自定义的FactoryBean需要实现FactoryBean的接口
*
* @author Administrator
*
*/
public class FactoryBeanImpl implements FactoryBean<Airplane> {
private int id;
private String type;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public Airplane getObject() throws Exception {
return new Airplane(id,type);
}
@Override
public Class<?> getObjectType() {
return Airplane.class;
}
@Override
public boolean isSingleton() {
return false;
}
}
添加配置:
<?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">
<!--通过FactoryBean来配置bean的实例-->
<!--
class : 指向FactoryBean的全类名
property: 配置FactoryBean的属性
实际返回的对象是FactoryBean的getObject方法返回的实例
-->
<bean id="airplane1" class="xyz.huning.spring4.factorybean.FactoryBeanImpl">
<property name="id" value="101"></property>
<property name="type" value="military"></property>
</bean>
</beans>
添加测试类:
package xyz.huning.spring4.factorybean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("factorybean.xml");
Airplane airplane1 = context.getBean("airplane1", Airplane.class);
System.out.println(airplane1);
((ClassPathXmlApplicationContext)context).close();
}
}