日积月累,水滴石穿 😄
Spring
可以通过factory-method
实例化对象。factory-method
方式是 Spirng
实例对象的方式之一。
创建对象的方式有两种方式:
- 一种是静态工厂注入(其中的方法必须是静态的)。
- 另一种是实例工厂注入。
下面一起来看看两种方式的使用方式
静态工厂注入
创建 A 对象,提供基本的属性和 get、set方法、构造函数、toString
方法。
public class A {
private String name;
private String email;
public A() {
}
public A(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "A{" +
"name='" + name + '\'' +
", email='" + email + '\'' +
'}';
}
}
静态工厂类
public class AFactory {
private static A a;
//静态方法 创建 A 对象
public static A getInstance(String name){
return new A(name);
}
}
添加配置
<!--静态获取Bean对象-->
<bean id="aFactory" class="com.gongj.factoryMethod.AFactory"
factory-method="getInstance">
<!--getInstance方法的参数-->
<constructor-arg index="0" value="GONGJ"></constructor-arg>
</bean>
class
属性指定工厂类的路径;factory-method
属性指定工厂类中静态方法,constrctor-arg
属性用于给静态方法传递参数。
测试
public static void main(String[] args) {
ClassPathXmlApplicationContext cxt = new ClassPathXmlApplicationContext("factoryMethod.xml");
Object aFactory = cxt.getBean("aFactory");
System.out.println("结果:" +aFactory);
}
结果:A{name='GONGJ', email='null'}
当然也可以指定参数获得对象:
Object aFactory = cxt.getBean("aFactory","哈哈哈哈");
System.out.println("结果:" +aFactory);
结果:A{name='哈哈哈哈', email='null'}
指定参数这种方式需要将 aFactory 的作用域改为 prototype。这里使用的 ClassPathXmlApplicationContext 容器,容器启动的时候就将 aFactory 创建了(懒加载单例bean),并使用 xml 指定的构造函数创建A
实例工厂注入
实例工厂方式需要先实例化工厂类,然后再通过已经实例化的工厂对象中一个方法来创建bean,并注入到容器中。
还是使用上面使用的 AFactory
类,在其中增加方法 getInstanceMethod
,与上述 getInstance
方法就少了一个 static
关键字。
public A getInstanceMethod(String name){
return new A(name);
}
修改配置
<!--实例化工厂类-->
<bean class="com.gongj.factoryMethod.AFactory" id="aFactory"></bean>
<!--实例化A对象 factory-bean配置实例化工厂类的名称 factory-method配置工厂类里的实例方法-->
<bean class="com.gongj.factoryMethod.A" id="a"
factory-bean="aFactory" factory-method="getInstanceMethod">
<constructor-arg index="0" value="yuanj"></constructor-arg>
</bean>
测试
public static void main(String[] args) {
ClassPathXmlApplicationContext cxt = new ClassPathXmlApplicationContext("factoryMethod.xml");
Object a = cxt.getBean("a");
System.out.println("结果:" +a);
}
结果:A{name='yuanj', email='null'}
也是可以指定参数获得对象:
Object a= cxt.getBean("a","哈哈哈哈");
System.out.println("结果:" +a);
结果:A{name='哈哈哈哈', email='null'}
这种方式需要将 a 的作用域改为 prototype
。
各位也会发现,两种方式获得对象的方式不一样。静态工厂创建对象时获取的对象是 cxt.getBean("aFactory");
,而实例工厂创建对象时获取的对象是cxt.getBean("a");
,当然两种方式返回的对象都是 A
。
学会了使用,我们看看源码是如何被解析的:直接进入 BeanDefinitionParserDelegate
类的 parseBeanDefinitionAttributes
方法,其中有这一段代码:
//解析 factory-method 属性
if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
}
//解析 factory-bean 属性
if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
}
很简单,获取 bean
标签里的 factory-method
属性的值,并赋值给 AbstractBeanDefinition
的 factoryMethodName
属性,获取 bean
标签里的 factory-bean
属性的值,并赋值给 AbstractBeanDefinition
的 factoryBeanName
属性。
- 如你对本文有疑问或本文有错误之处,欢迎评论留言指出。如觉得本文对你有所帮助,欢迎点赞和关注。