Java Spring FactoryBean用法

Java Spring FactoryBean用法,java,spring,Java,Spring,我有一个应用程序,我希望能够根据属性文件中的值切换DAO实现。SpringFactoryBean接口看起来工作得很好,因为我可以通过FactoryBean提供DAO,在FactoryBean中我可以根据属性值进行切换 然而,springsource博客文章的最后一段提到了以下警告: 这里有一个重要的收获,那就是生活在Spring容器中并享受生命周期挂钩和容器服务的是FactoryBean,而不是分解对象本身。返回的实例是暂时的-Spring不知道您从getObject()返回了什么,也不会尝试在

我有一个应用程序,我希望能够根据属性文件中的值切换DAO实现。SpringFactoryBean接口看起来工作得很好,因为我可以通过FactoryBean提供DAO,在FactoryBean中我可以根据属性值进行切换

然而,springsource博客文章的最后一段提到了以下警告:

这里有一个重要的收获,那就是生活在Spring容器中并享受生命周期挂钩和容器服务的是FactoryBean,而不是分解对象本身。返回的实例是暂时的-Spring不知道您从getObject()返回了什么,也不会尝试在其上执行任何生命周期挂钩或任何其他操作

MyDAO对象包含Spring注释
@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