Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java FactoryBeans和Spring3.0中基于注释的配置_Java_Spring_Inversion Of Control_Spring Annotations - Fatal编程技术网

Java FactoryBeans和Spring3.0中基于注释的配置

Java FactoryBeans和Spring3.0中基于注释的配置,java,spring,inversion-of-control,spring-annotations,Java,Spring,Inversion Of Control,Spring Annotations,Spring提供了FactoryBean接口,允许对Bean进行非平凡的初始化。该框架提供了许多工厂bean的实现,当使用Spring的XML配置时,工厂bean很容易使用 然而,在Spring3.0中,我找不到一种令人满意的方法将FactoryBean与基于注释的配置(néeJavaConfig)结合使用 显然,我可以手动实例化工厂bean,并自己设置任何必需的属性,如下所示: @Configuration public class AppConfig { ... @Bean

Spring提供了
FactoryBean
接口,允许对Bean进行非平凡的初始化。该框架提供了许多工厂bean的实现,当使用Spring的XML配置时,工厂bean很容易使用

然而,在Spring3.0中,我找不到一种令人满意的方法将FactoryBean与基于注释的配置(néeJavaConfig)结合使用

显然,我可以手动实例化工厂bean,并自己设置任何必需的属性,如下所示:

@Configuration
public class AppConfig {

...

    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
        factory.setDataSource(dataSource());
        factory.setAnotherProperty(anotherProperty());

        return factory.getObject();
    }
但是,如果
FactoryBean
实现了任何特定于Spring的回调接口,例如
初始化Bean
ApplicationContextAware
BeanClassLoaderware
、或
@PostConstruct
,那么这将失败。我还需要检查FactoryBean,找出它实现了什么回调接口,然后通过调用
setApplicationContext
afterPropertiesSet()
等自己实现这个功能

这让我觉得很尴尬:应用程序开发人员不应该实现IOC容器的回调


有人知道使用Spring Annotation configs中的FactoryBeans的更好的解决方案吗?

为什么不在AppConfiguration中注入Factory

@Configuration
public class AppConfig {

    @Resource
    private SqlSessionFactoryBean factory;

    @Bean 
    public SqlSessionFactory sqlSessionFactory() throws Exception {
       return factory.getObjectfactory();    
    }    
}

但我不明白你的问题是对的。因为在我看来,你正在尝试一些奇怪的事情-退一步,重新思考你真正需要的是什么。

据我所知,你的问题是你希望通过
sqlSessionFactory()
成为
sqlSessionFactory
(用于其他方法),但是您必须从
@Bean
注释的方法返回
SqlSessionFactoryBean
,才能触发Spring回调

可以通过以下解决方法解决此问题:

@Configuration 
public class AppConfig { 
    @Bean(name = "sqlSessionFactory")
    public SqlSessionFactoryBean sqlSessionFactoryBean() { ... }

    // FactoryBean is hidden behind this method
    public SqlSessionFactory sqlSessionFactory() {
        try {
            return sqlSessionFactoryBean().getObject();
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    @Bean
    public AnotherBean anotherBean() {
        return new AnotherBean(sqlSessionFactory());
    }
}

关键是对
@Bean
-带注释的方法的调用被一个方面截获,该方面对返回的Bean执行初始化(
FactoryBean
,在您的例子中),因此在
sqlSessionFactory()中对
sqlSessionFactoryBean()
的调用
返回一个完全初始化的
FactoryBean

以下是我的操作方法:

@Bean
def sessionFactoryBean: AnnotationSessionFactoryBean = {
  val sfb = new AnnotationSessionFactoryBean

  sfb.setDataSource(dataSource)
  sfb.setPackagesToScan(Array("com.foo.domain"))

  // Other configuration of session factory bean
  // ...

  return sfb
}

@Bean
def sessionFactory: SessionFactory = {
   return sessionFactoryBean.getObject
}
sessionFactoryBean被创建,适当的创建后生命周期的东西发生在它身上(AfterPropertieSet,等等)


注意,我没有直接将sessionFactoryBean作为bean引用。我将sessionFactory自动连接到我的其他bean中。

我认为,当您依靠自动连接时,这是最好的解决方法。如果您正在为bean使用Java配置,则如下所示:

@Bean
MyFactoryBean myFactory()
{ 
    // this is a spring FactoryBean for MyBean
    // i.e. something that implements FactoryBean<MyBean>
    return new MyFactoryBean();
}

@Bean
MyOtherBean myOther(final MyBean myBean)
{
    return new MyOtherBean(myBean);
}
@Bean
MyFactoryBean myFactory()
{ 
//这是MyBean的spring FactoryBean
//即实现FactoryBean的东西
返回新的MyFactoryBean();
}
@豆子
MyOtherBean myOther(最终MyBean MyBean)
{
返回新的MyOtherBean(myBean);
}
因此Spring将为我们注入myFactory().getObject()返回的MyBean实例,就像它对XML配置所做的那样

如果您在@Component/@Service等类中使用@Inject/@Autowire,这也应该起作用。

Spring JavaConfig有一个类,该类有一个getObject()方法用于FactoryBean

你可以用它来扩展

@Configuration
public class MyConfig extends ConfigurationSupport {

    @Bean
    public MyBean getMyBean() {
       MyFactoryBean factory = new MyFactoryBean();
       return (MyBean) getObject(factory);
    }
}
这是有一定背景的

在Spring3.0中,JavaConfig被移动到SpringCore中,并决定去掉这个类。建议的方法是现在使用构建器模式,而不是工厂模式

一个新的例子


一些背景知识

这就是我正在做的,它是有效的:

@Bean
@ConfigurationProperties("dataSource")
public DataSource dataSource() { // Automatically configured from a properties file
    return new BasicDataSource();
}

@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) throws Exception {
    SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
    factory.setDataSource(dataSource); // Invoking dataSource() would get a new instance which won't be initialized
    factory.setAnotherProperty(anotherProperty());
    return factory;
}


@Bean
public AnotherBean anotherBean(SqlSessionFactory sqlSessionFactory) { // This method receives the SqlSessionFactory created by the factory above
    return new AnotherBean(sqlSessionFactory);
}
您声明的任何bean都可以作为参数传递给任何其他@bean方法(再次调用相同的方法将创建一个新实例,而spring不会处理该实例)。 如果您声明一个FactoryBean,您可以使用它创建的bean类型作为另一个@bean方法的参数,它将接收正确的实例。 你也可以使用

@Autowired
private SqlSessionFactory sqlSessionFactory;

拉尔夫,谢谢你的回复,但是它不起作用,就像FactoryBean一样(在这个例子中,SqlSessionFactoryBean,但是它可以是任何实现
org.springframework.beans.factory.FactoryBean
——例如
org.springframework.orm.hibernate3.LocalSessionFactoryBean
)不在我的控制之下(或在我的源代码中),并且未使用@Value/@Resource/@Autowired/@Inject注释进行注释。因此,在我调用Spring上的
.getObject()
之前,Spring不会正确地注入它的依赖项。@Andrew Newdigate——工厂本身是XML配置的候选对象,或者如果您不喜欢XML,则在另一个@Bean注释的方法中创建它。(然后你可以使用@Value)我们每次在某处注入“MyBean”实例时,或者每个注入工厂都会创建新实例时,“MyBean”实例会是相同的吗?@KonstantinZyubin这取决于你如何实现该方法。但我不明白使用FactoryBean的好处在哪里。因为在这种情况下,我们可以使用静态工厂简单地创建常规bean,它将返回一个bean,结果将是相同的。是否希望在每次启动sqlSessionFactory时都创建一个新的SQl会话实例?
@Autowired
private SqlSessionFactory sqlSessionFactory;