Java 如何管理FactoryBean spring创建的bean?

Java 如何管理FactoryBean spring创建的bean?,java,spring,autowired,Java,Spring,Autowired,可以使用以编程方式创建可能需要复杂实例化逻辑的对象 但是,FactoryBean创建的bean似乎没有成为spring管理的。这个解释正确吗?如果有,有什么好的解决办法吗?包含一个简短的代码示例来说明我的问题 应用程序上下文: <bean id="searcher" class="some.package.SearcherFactory" /> <bean id="service" class="some.package.Service" /> 手动方式是: 在工厂

可以使用以编程方式创建可能需要复杂实例化逻辑的对象

但是,
FactoryBean
创建的bean似乎没有成为spring管理的。这个解释正确吗?如果有,有什么好的解决办法吗?包含一个简短的代码示例来说明我的问题

应用程序上下文:

<bean id="searcher" class="some.package.SearcherFactory" /> 
<bean id="service" class="some.package.Service" /> 
手动方式是:

  • 在工厂bean中注入依赖项
  • 在目标对象上手动设置它们
  • 您还可以将
    ApplicationContext
    注入工厂bean(或者通过实现
    ApplicationContextAware
    获得),并执行
    ctx.getAutowireCapableBeanFactory().autowireBean(bean)

    不过,我承认两人都感到奇怪


    但事实上,如果逻辑如此简单(仅实例化),请使用
    prototype
    范围。

    FactoryBean
    创建的对象由Spring管理,而不是由Spring实例化或配置。通过使用
    FactoryBean
    ,您自己承担责任。所有注入和配置必须由
    FactoryBean处理

    有一种可能更适合你的替代方法——使用。这意味着您可以在Java中使用复杂的实例化逻辑,同时仍然在对象本身上使用类似于
    @Autowired
    的东西


    我现在倾向于为所有非平凡的Spring应用程序使用注释样式配置,它使许多事情变得更加简单。

    这里是一个抽象的
    FactoryBean
    实现,它为您实现自动连接:

    public abstract class AbstractAutowiringFactoryBean<T> extends
        AbstractFactoryBean<T> implements ApplicationContextAware{
    
        private ApplicationContext applicationContext;
    
        @Override
        public void setApplicationContext(
            final ApplicationContext applicationContext){
            this.applicationContext = applicationContext;
        }
    
        @Override
        protected final T createInstance() throws Exception{
            final T instance = doCreateInstance();
            if(instance != null){
                applicationContext
                  .getAutowireCapableBeanFactory()
                  .autowireBean(instance);
            }
            return instance;
        }
    
        /**
         * Create the bean instance.
         * 
         * @see #createInstance()
         */
        protected abstract T doCreateInstance();
    
    }
    
    公共抽象类AbstractAutowiringFactoryBean扩展
    AbstractFactoryBean实现ApplicationContextAware{
    私有应用程序上下文应用程序上下文;
    @凌驾
    public void setApplicationContext(
    最终应用程序上下文(应用程序上下文){
    this.applicationContext=applicationContext;
    }
    @凌驾
    受保护的最终T createInstance()引发异常{
    final T instance=doCreateInstance();
    if(实例!=null){
    应用程序上下文
    .getAutowireCapableBeanFactory()的
    .autowireBean(实例);
    }
    返回实例;
    }
    /**
    *创建bean实例。
    * 
    *@see#createInstance()
    */
    受保护的抽象T doCreateInstance();
    }
    
    扩展它,实现
    getObjectType()
    doCreateInstance()
    方法,就可以启动并运行自动连接了

    注意:不应用BeanPostProcessor,这需要额外的代码。

    这怎么办

    <bean id="serviceFactory"
          class="some.package.SearcherFactory" />
    
    
    <bean id="service"
          factory-bean="serviceFactory"
          factory-method="getObject"/>
    
    
    

    。。。然后只注入bean“服务”,而不关心代码中的工厂

    FactoryBean是一个接口,作为开发人员,您在编写工厂类时实现了该接口,您希望工厂类创建的对象通过Spring作为bean进行管理,而另一方面,BeanFactory,表示SpringIOC容器,它包含托管bean并提供检索它们的访问。它是实现控制反转容器基本功能的框架核心的一部分

    File: context.xml
    
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="
                    http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="sha" class="MessageDigestFactoryBean">
            <property name="algorithm" value="SHA1"/>
        </bean>
    
        <bean id="md5" class="MessageDigestFactoryBean"/>
    
    </beans>
    
    
    File: Main.java
    
    import java.security.MessageDigest;
    
    import org.springframework.beans.factory.FactoryBean;
    import org.springframework.beans.factory.InitializingBean;
    import org.springframework.beans.factory.xml.XmlBeanFactory;
    import org.springframework.core.io.ClassPathResource;
    
    public class Main {
      public static void main(String[] args) {
        XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("context.xml"));
        String d1 = (String) factory.getBean("sha");
        String d2 = (String) factory.getBean("md5");
        System.out.println(d1);
        System.out.println(d2);
      }
    
    }
    
    class MessageDigestFactoryBean implements FactoryBean, InitializingBean {
      private static final String DEFAULT_ALGORITHM = "MD5";
    
      private String algorithm = DEFAULT_ALGORITHM;
    
      public Object getObject() throws Exception {
        return this.algorithm;
      }
    
      public Class getObjectType() {
        return MessageDigest.class;
      }
    
      public boolean isSingleton() {
        return true;
      }
    
      public void setAlgorithm(String algorithm) {
        this.algorithm = algorithm;
      }
    
      public void afterPropertiesSet() throws Exception {
        this.algorithm += " after setting";
      }
    }
    
    在大多数情况下,除非扩展框架的核心功能,否则您不会直接使用或实现BeanFactory接口。当您有工厂创建的对象需要由Spring管理时,您可以实现FactoryBean

    简而言之,BeanFactory表示Spring容器,而FactoryBean表示工厂类,其创建的对象被拾取并注册为容器中的bean

    File: context.xml
    
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="
                    http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="sha" class="MessageDigestFactoryBean">
            <property name="algorithm" value="SHA1"/>
        </bean>
    
        <bean id="md5" class="MessageDigestFactoryBean"/>
    
    </beans>
    
    
    File: Main.java
    
    import java.security.MessageDigest;
    
    import org.springframework.beans.factory.FactoryBean;
    import org.springframework.beans.factory.InitializingBean;
    import org.springframework.beans.factory.xml.XmlBeanFactory;
    import org.springframework.core.io.ClassPathResource;
    
    public class Main {
      public static void main(String[] args) {
        XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("context.xml"));
        String d1 = (String) factory.getBean("sha");
        String d2 = (String) factory.getBean("md5");
        System.out.println(d1);
        System.out.println(d2);
      }
    
    }
    
    class MessageDigestFactoryBean implements FactoryBean, InitializingBean {
      private static final String DEFAULT_ALGORITHM = "MD5";
    
      private String algorithm = DEFAULT_ALGORITHM;
    
      public Object getObject() throws Exception {
        return this.algorithm;
      }
    
      public Class getObjectType() {
        return MessageDigest.class;
      }
    
      public boolean isSingleton() {
        return true;
      }
    
      public void setAlgorithm(String algorithm) {
        this.algorithm = algorithm;
      }
    
      public void afterPropertiesSet() throws Exception {
        this.algorithm += " after setting";
      }
    }
    
    文件:context.xml
    文件:Main.java
    导入java.security.MessageDigest;
    导入org.springframework.beans.factory.FactoryBean;
    导入org.springframework.beans.factory.initializebean;
    导入org.springframework.beans.factory.xml.XmlBeanFactory;
    导入org.springframework.core.io.ClassPathResource;
    公共班机{
    公共静态void main(字符串[]args){
    XmlBeanFactory factory=newxmlbeanfactory(newclasspathResource(“context.xml”);
    字符串d1=(字符串)factory.getBean(“sha”);
    字符串d2=(字符串)factory.getBean(“md5”);
    系统输出打印项次(d1);
    系统输出打印项次(d2);
    }
    }
    类MessageDigestFactoryBean实现FactoryBean,初始化Bean{
    私有静态最终字符串DEFAULT_ALGORITHM=“MD5”;
    私有字符串算法=默认的_算法;
    公共对象getObject()引发异常{
    返回此参数。算法;
    }
    公共类getObjectType(){
    返回MessageDigest.class;
    }
    公共布尔isSingleton(){
    返回true;
    }
    公共void集合算法(字符串算法){
    这个算法=算法;
    }
    public void afterPropertieSet()引发异常{
    该算法+=“设置后”;
    }
    }
    
    它可以工作,并且至少可以将弹簧联轴器降低到单个工厂级别。+1。我刚刚开始使用基于注释的配置来处理这些类型的场景。那么,您将如何解决作者提出的问题呢?您能用适当的java配置更新答案吗?这也不是一个坏主意,可以提高可重用性。虽然我想知道为什么springsource的朋友们还没有将其作为模板提供。尝试了这一个,导致stacktrace出现问题,getObject()方法不存在。根据这个链接:一个service.getObject().getObject()将被调用。评论员并不打算照本宣科地复制上面的内容。在本例中,您的SearchFactory类型需要实现一个方法,如getObject(),该方法将返回所需类型的对象,或者您可以根据需要命名该方法。
    File: context.xml
    
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="
                    http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="sha" class="MessageDigestFactoryBean">
            <property name="algorithm" value="SHA1"/>
        </bean>
    
        <bean id="md5" class="MessageDigestFactoryBean"/>
    
    </beans>
    
    
    File: Main.java
    
    import java.security.MessageDigest;
    
    import org.springframework.beans.factory.FactoryBean;
    import org.springframework.beans.factory.InitializingBean;
    import org.springframework.beans.factory.xml.XmlBeanFactory;
    import org.springframework.core.io.ClassPathResource;
    
    public class Main {
      public static void main(String[] args) {
        XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("context.xml"));
        String d1 = (String) factory.getBean("sha");
        String d2 = (String) factory.getBean("md5");
        System.out.println(d1);
        System.out.println(d2);
      }
    
    }
    
    class MessageDigestFactoryBean implements FactoryBean, InitializingBean {
      private static final String DEFAULT_ALGORITHM = "MD5";
    
      private String algorithm = DEFAULT_ALGORITHM;
    
      public Object getObject() throws Exception {
        return this.algorithm;
      }
    
      public Class getObjectType() {
        return MessageDigest.class;
      }
    
      public boolean isSingleton() {
        return true;
      }
    
      public void setAlgorithm(String algorithm) {
        this.algorithm = algorithm;
      }
    
      public void afterPropertiesSet() throws Exception {
        this.algorithm += " after setting";
      }
    }