Java Spring FactoryBean用法
我有一个应用程序,我希望能够根据属性文件中的值切换DAO实现。SpringFactoryBean接口看起来工作得很好,因为我可以通过FactoryBean提供DAO,在FactoryBean中我可以根据属性值进行切换 然而,springsource博客文章的最后一段提到了以下警告: 这里有一个重要的收获,那就是生活在Spring容器中并享受生命周期挂钩和容器服务的是FactoryBean,而不是分解对象本身。返回的实例是暂时的-Spring不知道您从getObject()返回了什么,也不会尝试在其上执行任何生命周期挂钩或任何其他操作 MyDAO对象包含Spring注释Java Spring FactoryBean用法,java,spring,Java,Spring,我有一个应用程序,我希望能够根据属性文件中的值切换DAO实现。SpringFactoryBean接口看起来工作得很好,因为我可以通过FactoryBean提供DAO,在FactoryBean中我可以根据属性值进行切换 然而,springsource博客文章的最后一段提到了以下警告: 这里有一个重要的收获,那就是生活在Spring容器中并享受生命周期挂钩和容器服务的是FactoryBean,而不是分解对象本身。返回的实例是暂时的-Spring不知道您从getObject()返回了什么,也不会尝试在
@Repository
和@Transactional
。根据以上段落,如果我通过FactoryBean返回DAO实现,这些注释会被忽略吗?如果是这样,有什么好方法可以确保Spring管理FactoryBean返回的bean
编辑:似乎大多数人都在为该问题提供替代配置解决方案。虽然我对这些建议持开放态度(如果它们是好的,我会投票表决),但我的问题实际上与FactoryBean的正确使用有关,我将根据这些问题标记正确的答案。您可以在bean的
类
属性中使用属性占位符,因此,如果你有一个合理的命名约定,你可以
<bean id="customerDao" class="com.example.dao.${dao.type}.CustomerDao">
不使用工厂bean。您可以在bean的
类
属性中使用属性占位符,因此如果您有合理的命名约定,您可以使用
<bean id="customerDao" class="com.example.dao.${dao.type}.CustomerDao">
不要使用工厂bean。像往常一样使用@Component或XML在Spring上下文中创建DAO实例声明。假设它们都继承了一个公共接口,那么您可以稍后使用列表来收集它们。有关此类型收集机制的详细信息,请参阅此链接: 例如,在您的工厂中:
@Component
class MyCarDAOFactory implements ApplicationContextAware,FactoryBean<CarDAO> {
// Getters and Setters for the ApplicationContextAware interface..
ApplicationContext ctx;
// ...
// This will place any class that implements CarDAO from Spring Context.
@Inject
List<CarDAO> carDaoEntries;
// This method returns a CarDAO as classified by its Name property specified in
// a property placeholder value ( should it have been set in Spring context
// via a PropertyPlaceholder)
public CarDAO getObject() {
final String val = ctx.getEnvironment().getProperty("MY_PROPERTY_KEY");
return CollectionUtils.find(carDaoEntries, new Predicate() {
public boolean evaluate(Object object) {
return ((CarDAO) object).getName().startsWith(val);
}
});
}
}
@组件
类MyCarDAOFactory实现ApplicationContextAware,FactoryBean{
//ApplicationContextAware接口的getter和setter。。
应用上下文ctx;
// ...
//这将放置任何从Spring上下文实现CarDAO的类。
@注入
列出所有项目;
//此方法返回按中指定的名称属性分类的CarDAO
//属性占位符值(应在Spring上下文中设置)
//通过PropertyPlaceholder)
public-CarDAO-getObject(){
最后一个字符串val=ctx.getEnvironment().getProperty(“MY_属性_键”);
返回CollectionUtils.find(carDaoEntries,new Predicate(){
公共布尔求值(对象){
return((CarDAO)object.getName().startsWith(val);
}
});
}
}
现在,可能有一个更优雅/简单的解决方案来解决这类问题,如果有人可以的话
插上一个,然后请这样做 像往常一样使用@Component或XML在Spring上下文中创建DAO实例声明。假设它们都继承了一个公共接口,那么您可以稍后使用列表来收集它们。有关此类型收集机制的详细信息,请参阅此链接: 例如,在您的工厂中:
@Component
class MyCarDAOFactory implements ApplicationContextAware,FactoryBean<CarDAO> {
// Getters and Setters for the ApplicationContextAware interface..
ApplicationContext ctx;
// ...
// This will place any class that implements CarDAO from Spring Context.
@Inject
List<CarDAO> carDaoEntries;
// This method returns a CarDAO as classified by its Name property specified in
// a property placeholder value ( should it have been set in Spring context
// via a PropertyPlaceholder)
public CarDAO getObject() {
final String val = ctx.getEnvironment().getProperty("MY_PROPERTY_KEY");
return CollectionUtils.find(carDaoEntries, new Predicate() {
public boolean evaluate(Object object) {
return ((CarDAO) object).getName().startsWith(val);
}
});
}
}
@组件
类MyCarDAOFactory实现ApplicationContextAware,FactoryBean{
//ApplicationContextAware接口的getter和setter。。
应用上下文ctx;
// ...
//这将放置任何从Spring上下文实现CarDAO的类。
@注入
列出所有项目;
//此方法返回按中指定的名称属性分类的CarDAO
//属性占位符值(应在Spring上下文中设置)
//通过PropertyPlaceholder)
public-CarDAO-getObject(){
最后一个字符串val=ctx.getEnvironment().getProperty(“MY_属性_键”);
返回CollectionUtils.find(carDaoEntries,new Predicate(){
公共布尔求值(对象){
return((CarDAO)object.getName().startsWith(val);
}
});
}
}
现在,可能有一个更优雅/简单的解决方案来解决这类问题,如果有人可以的话
插上一个,然后请这样做 假设你有这样的东西:
public interface FooDao {
// ...
}
@Repository("firstFooDao")
public class FirstFooDao implements FooDao {
//...
}
@Repository("secondFooDao")
public class SecondFooDao implements FooDao {
//...
}
您可以创建一个配置类,以基于占位符(在本例中为foo
)返回适当的推进:
然后可以在属性文件中切换实现:
#foo=firstFooDao
foo=secondFooDao
这样,您的两个实现都由spring管理——这与您链接的文档中的示例不同,其中返回的对象是使用非spring工厂构建的。在本例中,所有bean都由spring实例化。配置类选择一个 假设你有这样的东西:
public interface FooDao {
// ...
}
@Repository("firstFooDao")
public class FirstFooDao implements FooDao {
//...
}
@Repository("secondFooDao")
public class SecondFooDao implements FooDao {
//...
}
您可以创建一个配置类,以基于占位符(在本例中为foo
)返回适当的推进:
然后可以在属性文件中切换实现:
#foo=firstFooDao
foo=secondFooDao
这样,您的两个实现都由spring管理——这与您链接的文档中的示例不同,其中返回的对象是使用非spring工厂构建的。在本例中,所有bean都由spring实例化。配置类选择一个 Spring Boot:AbstractFactoryBean用法
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import lombok.Getter;
import lombok.Setter;
enum ParsersConst {
bofafactory, jpmfactory, wellsforgofactory
}
interface Parser {
String readFromFile(String file);
void setKey(String key);
String getKey();
}
class JPM implements Parser {
private String key;
@Override
public String readFromFile(String file) {
System.out.println("From JPM Parser");
// LOGIC to read file data
return "JPM";
}
@Override
public void setKey(String key) {
this.key = key;
}
@Override
public String getKey() {
return key;
}
}
class Bofa implements Parser {
private String key;
@Override
public String readFromFile(String file) {
System.out.println("From Bofa Parser");
// LOGIC to read file data
return "BOFA";
}
@Override
public void setKey(String key) {
this.key = key;
}
@Override
public String getKey() {
return key;
}
}
class WellsForgo implements Parser {
private String key;
@Override
public String readFromFile(String file) {
System.out.println("From Wellsforgo Parser");
// LOGIC to read file data
return "WellsForgo";
}
@Override
public void setKey(String key) {
this.key = key;
}
@Override
public String getKey() {
return key;
}
}
class ParserCreator {
private Map<ParsersConst, Parser> parserMap;
public Parser createParser(ParsersConst parsConst) {
Parser parser = parserMap.get(parsConst);
if (parserMap.get(parsConst) != null) {
return parser;
}
throw new IllegalArgumentException("Unknown Parser");
}
public void setParserMap(Map<ParsersConst, Parser> parserMap) {
this.parserMap = parserMap;
}
}
@Getter
@Setter
class ParserFactory extends AbstractFactoryBean<Parser> {
private Parser parser;
private String key;
public ParserFactory(Parser parser, String key) {
this.parser = parser;
this.key = key;
}
@Override
public Class<?> getObjectType() {
return parser.getClass();
}
@Override
protected Parser createInstance() throws Exception {
parser.setKey(key);
return parser;
}
}
@Configuration
class ParserConfig {
@Bean
public ParserFactory jpmfactory() {
ParserFactory factory = new ParserFactory(jpm(), "XMYMK1@KML");
return factory;
}
@Bean
public ParserFactory bofafactory() {
ParserFactory factory = new ParserFactory(bofa(), "A2344567");
return factory;
}
@Bean
public ParserFactory wellsforgofactory() {
ParserFactory factory = new ParserFactory(wellsforgo(), "ABC345AAD");
return factory;
}
@Bean
public Parser bofa() {
return new Bofa();
}
@Bean
public Parser wellsforgo() {
return new WellsForgo();
}
@Bean
public Parser jpm() {
return new JPM();
}
}
@Component
public class StaticFacotryDemo implements CommandLineRunner {
@Autowired
private ApplicationContext context;
@Override
public void run(String... args) throws Exception {
Parser parser = (Parser) context.getBean(ParsersConst.jpmfactory.toString());
System.out.println(parser.getKey() + " " + parser.readFromFile("hello"));
}
}
import java.util.Map;
导入org.springframework.beans.factory.annotation.Autowired;
导入org.springframework.beans.factory.config.AbstractFactoryBean;
导入org.springframework.boot.CommandLineRunner;
导入org.springframework.context.ApplicationContext;
导入org.springframework.context.annotation.Bean;
导入org.springframework.context.annotation.Configuration;
导入org.springframework.stereotype.Component;
进口龙目吸气剂;
进口龙目织机;
枚举解析器常量{
bofafactory,jpmfactor