今天我们继续来学习IOC的两个知识点。
1.IOC通过工厂方法创建对象
2.IOC自动装载(autowire)
代码:
IOC通过工厂方法创建对象
我们之前说过IOC是典型的工厂模式,今天我们就来学习如何使用工厂模式来创建bean。
IOC通过工厂模式创建bean有两种方式:
1.静态工厂方法
2.实例工厂方法
按照惯例,我们还是通过代码来带大家去学习工厂方法。
首先来学习静态工厂方法。
1.创建Car实体类
public class Car {
private int num;
private String brand;
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public Car(int num, String brand) {
super();
this.num = num;
this.brand = brand;
}
public Car() {
super();
}
@Override
public String toString() {
return "Car [num=" + num + ", brand=" + brand + "]";
}
}
2.创建静态工厂类,静态工厂方法。
public class StaticCarFactory {
private static Map<Integer,Car> cars;
static{
cars = new HashMap<Integer,Car>();
cars.put(1, new Car(1,"奥迪"));
cars.put(2, new Car(2,"奥拓"));
}
public static Car getCar(int num){
return cars.get(id);
}
}
3.在spring.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">
<!-- 配置静态工厂创建car对象 -->
<bean id="car1" class="com.southwind.entity.StaticCarFactory" factory-method="getCar">
<constructor-arg value="1"></constructor-arg>
</bean>
</beans>
factory-method指向静态方法。
constructor-arg 的value属性为调用静态方法所传的参数。
4.在测试类中直接获取car1对象。
public class Test {
public static void main(String[] args) throws SQLException {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
Car car = (Car) applicationContext.getBean("car1");
System.out.println(car);
}
}
2.实例工厂方法
1.创建实例工厂类,工厂方法 。
public class InstanceCarFactory {
private Map<Integer,Car> cars;
public InstanceCarFactory() {
cars = new HashMap<Integer,Car>();
cars.put(1, new Car(1,"奥迪"));
cars.put(2, new Car(2,"奥拓"));
}
public Car getCar(int num){
return cars.get(num);
}
}
2.spring.xml中配置bean。
<?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="carFactory" class="com.southwind.entity.InstanceCarFactory"></bean>
<!-- 通过实例工厂对象创建car对象 -->
<bean id="car2" factory-bean="carFactory" factory-method="getCar">
<constructor-arg value="2"></constructor-arg>
</bean>
</beans>
3.在测试类中直接获取car2对象。
public class Test {
public static void main(String[] args) throws SQLException {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
Car car2 = (Car) applicationContext.getBean("car2");
System.out.println(car2);
}
}
对比两种方式的区别,静态工厂方法的方式创建car对象,不需要实例化工厂对象,因为静态工厂的静态方法,不需要创建对象即可调用。所以spring.xml只需要配置一个Car bean,而不需要配置工厂bean。
实例工厂方法创建car对象,必须先实例化工厂对象,因为调用的是非静态方法,必须通过对象调用,不能直接通过类来调用,所以spring.xml中需要先配置工厂bean,再配置Car bean。
其实这里考察的就是静态方法和非静态方法的调用。
IOC自动装载(autowire)
我们通过前面的学习,掌握了IOC创建对象的方式,以及DI完成依赖注入的方式,通过配置property的ref属性,可将bean进行依赖注入。
同时Spring还提供了另外一种更加简便的方式:自动装载,不需要手动配置property,IOC容器会自动选择bean完成依赖注入。
自动装载有两种方式:
byName:通过属性名自动装载
byType:通过属性对应的数据类型自动装载
通过代码来看。
1.创建Person实体类。
public class Person {
private int id;
private String name;
private Car car;
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 Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", car=" + car + "]";
}
}
2.spring.xml中配置Car bean和Person bean,并通过自动装载进行依赖注入。
创建person对象时,没有在property中配置car属性,所以IOC容器会自动进行装载,autowire="byName"表示通过匹配属性名的方式去装载对应的bean,Person实体类中有car属性,所以就将id="car"的bean注入到person中。
注意:通过property标签手动进行car的注入优先级更高,若两种方式同时配置,以property的配置为准。
<?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="person" class="com.southwind.entity.Person" autowire="byName">
<property name="id" value="1"></property>
<property name="name" value="张三"></property>
</bean>
<bean id="car" class="com.southwind.entity.StaticCarFactory" factory-method="getCar">
<constructor-arg value="2"></constructor-arg>
</bean>
</beans>
3.测试类中获取person对象。
public class Test {
public static void main(String[] args) throws SQLException {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
Person person = (Person) applicationContext.getBean("person");
System.out.println(person);
}
}
同理,byType即通过属性的数据类型来配置。
1.spring.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="person" class="com.southwind.entity.Person" autowire="byType">
<property name="id" value="1"></property>
<property name="name" value="张三"></property>
</bean>
<bean id="car" class="com.southwind.entity.StaticCarFactory" factory-method="getCar">
<constructor-arg value="1"></constructor-arg>
</bean>
<bean id="car2" class="com.southwind.entity.StaticCarFactory" factory-method="getCar">
<constructor-arg value="2"></constructor-arg>
</bean>
</beans>
2.测试类中获取person对象。
public class Test {
public static void main(String[] args) throws SQLException {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
Person person = (Person) applicationContext.getBean("person");
System.out.println(person);
}
}
会看到控制台直接打印错误信息,这是因为使用了byType进行自动装载,但是spring.xml中配置了两个Car bean,所以IOC容器不知道应该将哪一个bean装载到person对象中,所以报错。使用byType进行自动装载时,spring.xml中只能配置一个装载的bean。
3.现修改spring.xml配置,只保留一个bean。
<?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="person" class="com.southwind.entity.Person" autowire="byType">
<property name="id" value="1"></property>
<property name="name" value="张三"></property>
</bean>
<bean id="car" class="com.southwind.entity.StaticCarFactory" factory-method="getCar">
<constructor-arg value="1"></constructor-arg>
</bean>
</beans>
4.测试类中获取person对象。
成功。
源码:
链接: https://pan.baidu.com/s/1dGDryG5
密码: k4wd