factory-bean

spring的bean标签的一个属性,用来指定创建实例的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class ClientService {
private static ClientService clientService = new ClientService();
private ClientService() {}

public static ClientService createInstance() {
return clientService;
}
}

public class DefaultServiceLocator {

private static ClientService clientService = new ClientServiceImpl();
private static AccountService accountService = new AccountServiceImpl();

private DefaultServiceLocator() {}

public ClientService createClientServiceInstance() {
return clientService;
}

public AccountService createAccountServiceInstance() {
return accountService;
}

}

第一种写法

1
2
3
<bean id="clientService"
class="examples.ClientService"
factory-method="createInstance"/>

这种写法要求factory-method必须是static

第二种写法

1
2
3
4
5
6
7
8
9
10
11
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
<!-- inject any dependencies required by this locator bean -->
</bean>

<bean id="clientService"
factory-bean="serviceLocator"
factory-method="createClientServiceInstance"/>

<bean id="accountService"
factory-bean="serviceLocator"
factory-method="createAccountServiceInstance"/>

这种写法多了一个factory-bean,指定了使用哪个类的哪个方法去创建,不要求这个方法是static,但是factory-bean对应的类必须交由spring管理。

一个类中可以包含多个创建的方法。

FactoryBean

是Spring提供的一个接口,用来定制Bean的初始化逻辑。

If you have complex initialization code that is better expressed in Java as opposed to a (potentially) verbose amount of XML, you can create your own FactoryBean

Interface to be implemented by objects used within a {@link BeanFactory} which
are themselves factories for individual objects. If a bean implements this
interface, it is used as a factory for an object to expose, not directly as a
bean instance that will be exposed itself.

这个接口有三个方法:

  • Object getObject()

获取创建的对象

  • boolean isSingleton()

返回的对象是否是单例的

  • Class getObjectType()

获取返回的对象的类型

GsonFactoryBean就实现了FactoryBean接口,是一个不错的例子,大概代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
public class GsonFactoryBean implements FactoryBean<Gson>, InitializingBean {

private boolean base64EncodeByteArrays = false;

private boolean serializeNulls = false;

private boolean prettyPrinting = false;

private boolean disableHtmlEscaping = false;

private String dateFormatPattern;

private Gson gson;

public void setBase64EncodeByteArrays(boolean base64EncodeByteArrays) {
this.base64EncodeByteArrays = base64EncodeByteArrays;
}

public void setSerializeNulls(boolean serializeNulls) {
this.serializeNulls = serializeNulls;
}

public void setPrettyPrinting(boolean prettyPrinting) {
this.prettyPrinting = prettyPrinting;
}

public void setDisableHtmlEscaping(boolean disableHtmlEscaping) {
this.disableHtmlEscaping = disableHtmlEscaping;
}

public void setDateFormatPattern(String dateFormatPattern) {
this.dateFormatPattern = dateFormatPattern;
}


@Override
public void afterPropertiesSet() {
GsonBuilder builder = (this.base64EncodeByteArrays ?
GsonBuilderUtils.gsonBuilderWithBase64EncodedByteArrays() : new GsonBuilder());
if (this.serializeNulls) {
builder.serializeNulls();
}
if (this.prettyPrinting) {
builder.setPrettyPrinting();
}
if (this.disableHtmlEscaping) {
builder.disableHtmlEscaping();
}
if (this.dateFormatPattern != null) {
builder.setDateFormat(this.dateFormatPattern);
}
this.gson = builder.create();
}

@Override
public Gson getObject() {
return this.gson;
}

@Override
public Class<?> getObjectType() {
return Gson.class;
}

@Override
public boolean isSingleton() {
return true;
}

}

GsonFactoryBean除了实现了FactoryBean接口,还实现了InitializingBean接口,这个接口只有一个方法

afterPropertiesSet。这个方法会在bean的所有提供的属性被设置之后,被BeanFactory调用,是spring保留的一个扩展点。

GsonFactoryBean在这个方法中将收集到的配置信息传给builder,构建出一个Gson对象(这种一般是大对象,一个容器中有一个就够了)。

1
2
3
4
5
  <bean id="gsonFactoryBean" class="org.springframework.http.converter.json.GsonFactoryBean">
<property name="dateFormatPattern" value="yyyy-MM-dd"/>
<property name="disableHtmlEscaping" value="true"/>
<property name="prettyPrinting" value="true"/>
</bean>

参考

  1. 7. The IoC container