繁体   English   中英

非JSR299 Bean不能用于生产者方法

[英]Non-JSR299 bean cannot be proxied for producer method

我知道,如果通过生产者方法实例化,则可以将不兼容JSP-299的类用于注入。

我将其解释为,如果我想使用带有参数的构造函数使可注入的Bean可以通过使用生产者方法来实现。

但是,当我这样做时,在部署时会出现以下异常:

2015-11-11T21:35:12.099+0000|Grave: Exception during lifecycle processing
org.glassfish.deployment.common.DeploymentException: CDI deployment failure:Exception List with 2 exceptions:
Exception 0 :
org.jboss.weld.exceptions.DeploymentException: WELD-001435 Normal scoped bean class org.....MongoConfiguration is not proxyable because it has no no-args constructor - Producer Method [MongoConfiguration] with qualifiers [@Any @Default] declared as [[BackedAnnotatedMethod] @Produces @ApplicationScoped public org.....PropertiesProducer.produceMongoConfiguration()]. 

这是生产者:

public class PropertiesProducer {

    private static final String PROPERTIES_FILE = "mongo.properties";

    private Properties properties = new Properties();

    public static final String DATABASE_NAME        = "database.name";
    public static final String PORT                 = "database.port";
    public static final String HOST                 = "database.host";
    public static final String USERNAME             = "database.username";
    public static final String PASSWORD             = "database.password";

    @Produces
    @ApplicationScoped
    public MongoConfiguration produceMongoConfiguration(){

        final InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(PROPERTIES_FILE);
        if (in == null) {
            return new MongoConfiguration(properties);
        }
        try {
            properties.load(in);
        } catch (IOException e) {
            throw new RuntimeException("Failed to load properties", e);
        }
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                // don't care
            }
        }

        return new MongoConfiguration(properties);
    }
}

用法如下:

public class MongoDatastore {

    @Inject
    MongoConfiguration mongoConfiguration;

    @Inject
    MongoClient mongoClient;
    Datastore datastore;

    @PostConstruct
    private void setupDatastore() {
        Morphia morphia = new Morphia();
        datastore = morphia.createDatastore(mongoClient, mongoConfiguration.getDatabaseName());
    }

 }

我是否错过了一些显而易见的事情?

最简单的解决方案是将范围从@ApplicationScoped更改为@Singleton

import javax.inject.Singleton;

@Produces
@Singleton
public MongoConfiguration produceMongoConfiguration(){
     // ...
     return new MongoConfiguration(properties);
}

为了澄清起见,您可以看到此SO答案

顺便说一句:普通作用域@ApplicationScoped通常优于@Singleton伪作用域。 为什么? 例如,因为此类bean的序列化+反序列化将完美地工作。 但是在日常工作中,有时我们会遇到不可替代的第三部分类 ,因此我们无法更改。 因此,我们有可能的解决方案:

  • 使用@Singleton伪作用域。
  • 创建一个接口,并使用该接口代替具体的Bean(内部生产者方法返回类型和常规代码)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM