spring注⼊bean的三种⽅法
在Spring的世界中,我们通常会利⽤bean config file 或者 annotation注解⽅式来配置bean.
在第⼀种利⽤bean config file(spring xml)⽅式中,还包括如下三⼩类
1. 反射模式
2. ⼯⼚⽅法模式(本⽂重点)
3. Factory Bean模式
其中反射模式最常见,我们需要在bean 配置中指明我们需要的bean object的全类名。
例如:
<bean id="car1" class="com.home.factoryMethod.Car">
<property name="id" value="1"></property>
<property name="name" value="Honda"></property>
<property name="price" value="300000"></property>
</bean>
上⾯bean ⾥⾯的class属性就是全类名, Spring利⽤java反射机制创建这个bean。
Factory⽅法模式
本⽂介绍的是另1种模式,在⼯⼚⽅法模式中, Spring不会直接利⽤反射机制创建bean对象,⽽是会利⽤反射机制先到Factory类,然后利⽤Factory再去⽣成bean对象。
⽽Factory Mothod⽅式也分两种,分别是静态⼯⼚⽅法和实例⼯⼚⽅法。
静态⼯⼚⽅法⽅式
所谓镜头静态⼯⼚⽅式就是指Factory类不本⾝不需要实例化,这个Factory类中提供了1个静态⽅法来⽣成bean对象
下⾯是例⼦
bean类Car
⾸先我们定义1个bean类Car
package com.home.factoryMethod;
public class Car {
private int id;
private String name;
private int price;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
实例化bean的三种方式this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public String toString() {
return "Car [id=" + id + ", name=" + name + ", price=" + price + "]";
}
public Car(){
}
public Car(int id, String name, int price) {
super();
this.id = id;
this.name = name;
this.price = price;
}
}
然后我们再定义1个⼯⼚类CarStaticFactory
package com.home.factoryMethod;
import java.util.HashMap;
import java.util.Map;
public class CarStaticFactory {
private static Map<Integer, Car> map = new HashMap<Integer,Car>();
static{
map.put(1, new Car(1,"Honda",300000));
map.put(2, new Car(2,"Audi",440000));
map.put(3, new Car(3,"BMW",540000));
}
public static Car getCar(int id){
(id);
}
}
⾥⾯定义了1个静态的bean 容器map. 然后提供1个静态⽅法根据Car 的id 来获取容器⾥的car对象。
xml配置
<!--
Static Factory method:
class: the class of Factory
factory-method: method of get Bean Object
constructor-arg: parameters of factory-method
-->
<bean id="bmwCar" class="com.home.factoryMethod.CarStaticFactory" factory-method="getCar">
<constructor-arg value="3"></constructor-arg>
</bean>
<bean id="audiCar" class="com.home.factoryMethod.CarStaticFactory" factory-method="getCar">
<constructor-arg value="2"></constructor-arg>
</bean>
可以见到,利⽤静态⼯⼚⽅法定义的bean item种, class属性不在是bean的全类名,⽽是静态⼯⼚的全类名,⽽且还需要指定⼯⼚⾥的getBean 静态⽅法名字和参数
客户端代码
public static void h(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("l");
Car car1 = (Car) Bean("bmwCar");
System.out.println(car1);
car1 = (Car) Bean("audiCar");
System.out.println(car1);
}
输出
May 30, 2016 11:17:45 PM t.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing t.support.ClassPathXmlApplicationContext@43765ab3: startup date [Mon May 30 23:17:45 CST 2016]; root of context hierarchy May 30, 2016 11:17:46 PM org.springframework.l.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [l]
Car [id=3, name=BMW, price=540000]
Car [id=2, name=Audi, price=440000]
⼩结
由上⾯的例⼦,静态⼯⼚⽅法⽅式是⾮常适⽤于作为1个bean容器(集合的), 只不过吧bean集合定义在⼯⼚类⾥⾯⽽不是bean config file⾥⾯。缺点也⽐较明显,把数据写在class⾥⾯⽽不是配置⽂件中违反了我们程序猿的常识和spring的初衷。当然优点就是令到令⼈恶⼼的bean config file更加简洁啦。
实例⼯⼚⽅法⽅式
所谓实例⼯⼚⽅式也很容易看懂,就是⾥⾯的getBean ⽅法不是静态的,也就是代表要先实例1个⼯⼚对象,才能依靠这个⼯⼚对象去获得bean 对象。
⽤回上⾯的例⼦。
⽽这次我们写1个实例⼯⼚类
CarInstanceFactroy
package com.home.factoryMethod;
import java.util.HashMap;
import java.util.Map;
public class CarInstanceFactory {
private Map<Integer, Car> map = new HashMap<Integer,Car>();
public void setMap(Map<Integer, Car> map) {
this.map = map;
}
public CarInstanceFactory(){
}
public Car getCar(int id){
(id);
}
}
bean xml写法
<!-- Instance Factory Method:
1.must create a bean for the Instance Factroy First
-->
<bean id="carFactory" class="com.home.factoryMethod.CarInstanceFactory">
<property name="map">
<map>
<entry key="4">
<bean class="com.home.factoryMethod.Car">
<property name="id" value="4"></property>
<property name="name" value="Honda"></property>
<property name="price" value="300000"></property>
</bean>
</entry>
<entry key="6">
<bean class="com.home.factoryMethod.Car">
<property name="id" value="6"></property>
<property name="name" value="ford"></property>
<property name="price" value="500000"></property>
</bean>
</entry>
</map>
</property>
</bean>
<!-- 2.use Factory bean to get bean objectr
factory-bean : the bean define above
factory-method: method of get Bean Object
constructor-arg: parameters of factory-method
-->
<bean id="car4" factory-bean="carFactory" factory-method="getCar">
<constructor-arg value="4"></constructor-arg>
</bean>
<bean id="car6" factory-bean="carFactory" factory-method="getCar">
<constructor-arg value="6"></constructor-arg>
</bean
因为实例⼯⼚本⾝要实例化,所以我们可以在xml中指定它⾥⾯容器的data,解决了上⾯提到的静态⼯⼚⽅法的缺点啦
client代码
public static void h2(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("l");
Car car1 = (Car) Bean("car4");
System.out.println(car1);
car1 = (Car) Bean("car6");
System.out.println(car1);
}
输出结果
May 31, 2016 12:22:28 AM t.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing t.support.ClassPathXmlApplicationContext@5d79a4c9: startup date [Tue May 31 00:22:28 CST 2016]; root of context hierarchy May 31, 2016 12:22:28 AM or
g.springframework.l.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [l]
Car [id=4, name=Honda, price=300000]
Car [id=6, name=ford, price=500000]
⼩结
本⼈觉得实例⼯⼚⽅式使⽤起来更加灵活啦,不过项⽬中其实本⽂⼀开始提到的第三种⽅法FactoryBean⽐起⼯⼚⽅法⽅式更加常见。