当我们在Spring中使用第三方类库,但是Spring官方又没有提供相应的集成jar包,而我们又希望Spring能够管理它时,此时可以通过实现FactoryBean接口来达到这个目的。为了Spring能够控制第三方类对象的生命周期,我们还可以实现InitializingBean和DisposableBean接口,或者通过在bean注册时声明初始化(init-method)和结束(destroy-method)方法实现。
下面以elasticsearch的TransportClient对象为例,使Spring简单集成5.x版本的transportClient:
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import java.net.InetAddress;
public class ESTransportClientFactoryBean implements FactoryBean<TransportClient>,InitializingBean,DisposableBean {
private String clusterName;
private String host;
private int port;
private TransportClient client;
public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}
public void setHost(String host) {
this.host = host;
}
public void setPort(int port) {
this.port = port;
}
public TransportClient getObject() throws Exception {
return client;
}
public Class<?> getObjectType() {
return TransportClient.class;
}
public boolean isSingleton() {
return false;
}
public void destroy() throws Exception {
if(client!=null)
client.close();
}
public void afterPropertiesSet() throws Exception {
Settings settings=Settings.builder().put("cluster.name",this.clusterName).build();
client=new PreBuiltTransportClient(settings).addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(this.host),this.port));
}
}
当注册factoryBean时,实际上注册的是getObject()方法的返回值,可以理解为bean工厂生产bean,而bean的id为factoryBean注册时的id。
下面是注册factoryBean的例子:
@Configuration
@ComponentScan(basePackages = {"com.search"},
excludeFilters = {@ComponentScan.Filter(type= FilterType.ANNOTATION,value = Controller.class)})
@EnableTransactionManagement
public class RootConfig {
...
//bean的id为transportClient
@Bean
public ESTransportClientFactoryBean transportClient(){
ESTransportClientFactoryBean transportClientFactory=new ESTransportClientFactoryBean();
transportClientFactory.setClusterName("cluster");
transportClientFactory.setHost("192.168.1.206");
transportClientFactory.setPort(9300);
return transportClientFactory;
}
...
}
然后,需要使用时直接注入,例:
@Autowired
private TransportClient transportClient;