【问题标题】:Java Spring bean with private constructor具有私有构造函数的 Java Spring bean
【发布时间】:2011-11-07 10:38:57
【问题描述】:

在 Spring 中,bean 的类是否可能没有公共构造函数而只有私有构造函数? 创建 bean 时会调用这个私有构造函数吗? 谢谢。

【问题讨论】:

  • 试一试然后发布结果如何?
  • 这很难 - 我没有所有来源。

标签: java spring constructor javabeans private


【解决方案1】:

是的,Spring 可以调用私有构造函数。如果它找到具有正确参数的构造函数,无论可见性如何,它将使用反射将其构造函数设置为可访问。

【讨论】:

  • 能否给我参考文档?构造函数有参数,并在xml文件中给这个参数赋值。
  • 你的意思是如果一个 bean 有专门的东西,比如 private bean() { ... } spring 可以调用它吗?这怎么可能,这违背了“私人”的全部目的。
  • 对不起,我可能错了,它只是无参数构造函数。我只是按照我在自己的项目中注意到的。我不能说我在任何地方的 Spring 文档中都见过它。但这是负责进行实例化的类的 javadoc。 static.springsource.org/spring/docs/3.0.x/javadoc-api/org/…
  • @Ashkan 可以使用反射。特别是,Spring BeanUtils 类使用一个名为 ReflectionUtils 的类来使构造函数可访问。请参阅 Constructor.setAccessible() 的 javadocs。
  • @Kevin Stembridge 你是对的,可以使用反射。
【解决方案2】:

您始终可以使用工厂方法来创建 bean,而不是依赖默认构造函数,来自 The IoC container: Instantiation using an instance factory method

<!-- the factory bean, which contains a method called createInstance() -->
<bean id="serviceLocator" class="com.foo.DefaultServiceLocator">
  <!-- inject any dependencies required by this locator bean -->
</bean>

<!-- the bean to be created via the factory bean -->
<bean id="exampleBean"
      factory-bean="serviceLocator"
      factory-method="createInstance"/>

这样做的好处是你可以为你的bean使用非默认构造函数,并且工厂方法bean的依赖也可以被注入。

【讨论】:

  • 很有趣,但我找不到工厂。可能以另一种方式存在?
  • @Matthew:他似乎正在围绕一些丑陋的第三方代码改造 Spring。那只是必然会很乱。
  • @Donal,不,我不明白他在评论中说了什么。
  • 你能告诉我这个xml配置对应的java配置是什么吗?
【解决方案3】:

是的,私有构造函数由 spring 调用。 考虑我的代码:

Bean定义文件:

<bean id="message" class="com.aa.testp.Message">
        <constructor-arg index="0" value="Hi Nice"/>
    </bean>

豆类:

package com.aa.testp;

public class Message {

    private String message;

    private Message(String msg) {
       // You may add your log or print statements to check execution or invocation
        message = msg;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public void display() {
        System.out.println(" Hi " + message);
    }

}

上面的代码工作正常。因此,spring 调用了私有构造函数。

【讨论】:

  • 有人知道如何使用 Spring Java 配置(不是基于 xml)来做到这一点吗?
【解决方案4】:

是的! Spring 可以访问私有构造函数。 它将像下面的代码一样在内部工作。

 try {
    Class clazz = Class.forName("A"); // A - Fully qualified class name
    Constructor constructor[] = clazz.getDeclaredConstructors();
    constructor[0].setAccessible(true);
    A a = (A) constructor[0].newInstance();
 }
 catch (Exception e) {
        e.printStackTrace();
 }

【讨论】:

    【解决方案5】:

    您通常在此类 bean 中有一个静态工厂方法,您可以为 spring 指定该方法以获取该 bean 的实例。请参阅 3.3.1.3 here. 这是 Spring 推荐的方式,而不是违反可见性限制。

    【讨论】:

    • 奇怪,没有静态方法,没有公共构造函数,但是当我进行调试时 - 调用了私有构造函数!通过 sun.reflect.NativeConstructorAccessorImpl
    • 如果没有细节/代码,将无法进一步评论!
    • 我想你错了。没有特定的代码 - 我在调试器中看到的只有标准的 sun/spring 方法。
    • @Ashkan:我怀疑你得到了 -1 票,因为你错了。 Spring可以窥视幕后(除非有严格的安全管理器,并且 Spring 代码未标记为受信任)。
    • @Ashkan:违反可见性限制是非常糟糕的风格。不要这样做!或者如果你这样做了,你会觉得很糟糕。 (Spring 这样做是因为它想将 bean 的定义与其配置分开,但它们通常仍然紧密相连。这个问题恰好是关于不正确的例外情况......)
    【解决方案6】:

    Spring 永远不会将私有构造函数调用为 Bean 作用域。如果这样做会出现以下错误。

    此问题的常见原因包括使用最终类或不可见类。嵌套异常是

    java.lang.IllegalArgumentException:类中没有可见的构造函数。

    【讨论】:

      猜你喜欢
      • 2012-02-05
      • 2012-08-04
      • 2011-12-26
      • 1970-01-01
      • 1970-01-01
      • 2014-02-08
      • 1970-01-01
      • 1970-01-01
      • 2017-03-28
      相关资源
      最近更新 更多