How get working @Value or Environment in a class implementing the Condition/ConfigurationCondition interfaces

六月ゝ 毕业季﹏ 提交于 2019-12-02 11:06:36

问题


I am working with only JavaConfig.

I have the following declaration:

@Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
    return new PropertySourcesPlaceholderConfigurer();
}

it is mandatory for JavaConfig according with the following post: Spring 3.2 @value annotation with pure java configuration does not work, but Environment.getProperty works

The following code works perfect (many @Values by testing purposes):

@Configuration
public class ActiveMQServerConfiguration {

    @Value("${localhost.address}")
    private String localHost;

    @Value("${remotehost.address}")
    private String remoteHost;

    @Value("${localhost.port}")
    private Integer localPort;

    @Value("${remotehost.port}")
    private Integer remotePort;

    @Bean(name="connectionFactory")
    @Conditional(LocalHostStatusCondition.class)
    public ActiveMQConnectionFactory localConnectionFactory(
            @Value("${localhost.protocol}") String protocol,
            @Value("${localhost.address}") String host,
            @Value("${localhost.port}") String port ){

        System.out.println("protocol: "+protocol);
        System.out.println("host: "+host);
        System.out.println("port: "+port);

        System.out.println("localHost: "+localHost);
        System.out.println("localPort: "+localPort);
        System.out.println("remoteHost: "+remoteHost);
        System.out.println("remotePort: "+remotePort);

I can see in the console/terminal

Alpha

protocol: tcp
host: 127.0.0.1
port: 61616
localHost: 127.0.0.1
localPort: 61616
remoteHost: 192.168.1.34
remotePort: 61616

But the following does not works how expected:

public class LocalHostStatusCondition implements Condition {

    private static final Logger logger = LoggerFactory.getLogger(LocalHostStatusCondition.class);

    @Value("${localhost.address}")
    private String localHost;

    @Value("${remotehost.address}")
    private String remoteHost;

    @Value("${localhost.port}")
    private Integer localPort;

    @Value("${remotehost.port}")
    private Integer remotePort;

    @Autowired
    private Environment environment;

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        logger.info("LocalHostStatusCondition...");

        System.out.println("localHost: "+localHost);
        System.out.println("localPort: "+localPort);
        System.out.println("remoteHost: "+remoteHost);
        System.out.println("remotePort: "+remotePort);
        System.out.println("Env..." + environment.getProperty("localhost.address", String.class) );

Practically the same and even working with Environment

The output is:

Beta

localHost: null
localPort: null
remoteHost: null
remotePort: null
[WARNING] 
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:293)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NullPointerException
    at com.manuel.jordan.infrastructure.support.LocalHostStatusCondition.matches(LocalHostStatusCondition.java:42)

According with the Condition API:

Conditions must follow the same restrictions as BeanFactoryPostProcessor and take care to never interact with bean instances. For more fine-grained control of conditions that interact with @Configuration beans consider the ConfigurationCondition interface.

About ConfigurationCondition I have read this When to use Spring @ConfigurationCondition vs. @Condition? too

I have edited to the following:

public class LocalHostStatusCondition implements ConfigurationCondition {

…

    @Override
    public ConfigurationPhase getConfigurationPhase() {
        return ConfigurationPhase.PARSE_CONFIGURATION;
    }

If I use:

  • ConfigurationPhase.REGISTER_BEAN I get the same output how Beta
  • ConfigurationPhase.PARSE_CONFIGURATION; I get no errors but...

but the console/terminal does not show nothing about the sentences working, I mean, System.out are not printing (I don't understand about this weird behaviour).

How I can resolve this?

I need have working @Value or Environment, it with the purpose to let know the application if should connect to a local or remote ActiveMQ server.

And yes, I have read the following: How do I delay evaluation of a Spring @Conditional configuration annotation? seems there is no solution…

Thank You


回答1:


You have

@Conditional(LocalHostStatusCondition.class)

Spring takes the Class type you've specified and instantiates it to use its matches method. It doesn't consider the instance as a bean, it doesn't perform autowiring on it, nor any @Value processing. The latter are true for BeanFactoryPostProcessor as well.

You can retrieve the Environment from the ConditionContext if you want to. The alternative is to load the properties yourself.



来源:https://stackoverflow.com/questions/25276463/how-get-working-value-or-environment-in-a-class-implementing-the-condition-conf

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!