Java 我们可以有条件地声明Springbean吗?

Java 我们可以有条件地声明Springbean吗?,java,spring,Java,Spring,有没有一种方法可以有条件地声明Springbean,如: <bean class="path.to.the.class.MyClass" if="${1+2=3}" /> 这将是有用的,而不必使用配置文件。 我脑子里没有具体的用例,但我想到了。您可以使用Spring4中的@Conditional或SpringBoot中的@Conditional属性 使用Spring4(仅限) 如果您未使用Spring启动,则此可能会造成过度伤害 首先,创建一个条件类,其中条件上下文可以访问环境

有没有一种方法可以有条件地声明Springbean,如:

<bean class="path.to.the.class.MyClass" if="${1+2=3}" />

这将是有用的,而不必使用配置文件。
我脑子里没有具体的用例,但我想到了。

您可以使用Spring4中的@Conditional或SpringBoot中的@Conditional属性

  • 使用Spring4(仅限
  • 如果您未使用Spring启动,则此可能会造成过度伤害

    首先,创建一个
    条件
    类,其中
    条件上下文
    可以访问
    环境

    public class MyCondition implements Condition {
        @Override
        public boolean matches(ConditionContext context,
                               AnnotatedTypeMetadata metadata) {
            Environment env = context.getEnvironment();
            return null != env
                    && "true".equals(env.getProperty("server.host"));
        }
    }
    
    然后为bean添加注释:

    @Bean
    @Conditional(MyCondition.class)
    public ObservationWebSocketClient observationWebSocketClient() {
        //return bean
    }
    
    2.使用弹簧护套

    @ConditionalOnProperty(name="server.host", havingValue="localhost")
    
    在您的
    abcd.properties
    文件中

    server.host=localhost
    

    我有一个关于这件事的片段。它检查在注释中设置的属性的值,因此您可以使用

    @ConditionalOnProperty(value="usenew", on=false, propertiesBeanName="myprops")
    @Service("service")
    public class oldService implements ServiceFunction{
        // some old implementation of the service function.
    }
    
    它甚至允许您使用相同的名称定义不同的bean:

    @ConditionalOnProperty(value="usenew", on=true, propertiesBeanName="myprops")
    @Service("service")
    public class newService implements ServiceFunction{
        // some new implementation of the service function.
    }
    
    这两个可以同时声明,允许您拥有一个名为“服务”的bean,根据属性是开还是关,它有不同的实现

    它本身的代码片段:

    /**
     * Components annotated with ConditionalOnProperty will be registered in the spring context depending on the value of a
     * property defined in the propertiesBeanName properties Bean.
     */
    
    @Target({ ElementType.TYPE, ElementType.METHOD })
    @Retention(RetentionPolicy.RUNTIME)
    @Conditional(OnPropertyCondition.class)
    public @interface ConditionalOnProperty {
        /**
         * The name of the property. If not found, it will evaluate to false.
         */
        String value();
        /**
         * if the properties value should be true (default) or false
         */
        boolean on() default true;
        /**
         * Name of the bean containing the properties.
         */
        String propertiesBeanName();
    }
    
    /**
     * Condition that matches on the value of a property.
     *
     * @see ConditionalOnProperty
     */
    class OnPropertyCondition implements ConfigurationCondition {
        private static final Logger LOG = LoggerFactory.getLogger(OnPropertyCondition.class);
    
        @Override
        public boolean matches(final ConditionContext context, final AnnotatedTypeMetadata metadata) {
            final Map attributes = metadata.getAnnotationAttributes(ConditionalOnProperty.class.getName());
            final String propertyName = (String) attributes.get("value");
            final String propertiesBeanName = (String) attributes.get("propertiesBeanName");
            final boolean propertyDesiredValue = (boolean) attributes.get("on");
    
            // for some reason, we cannot use the environment here, hence we get the actual properties bean instead.
            Properties props = context.getBeanFactory().getBean(propertiesBeanName, Properties.class);
            final boolean propValue = parseBoolean(props.getProperty(propertyName, Boolean.toString(false)));
            LOG.info("Property '{}' resolved to {}, desired: {}", new Object[] { propertyName, propValue, "" + propertyDesiredValue });
            return propValue == propertyDesiredValue;
        }
        /**
         * Set the registration to REGISTER, else it is handled during  the parsing of the configuration file
         * and we have no guarantee that the properties bean is loaded/exposed yet
         */
        @Override
        public ConfigurationPhase getConfigurationPhase() {
            return ConfigurationPhase.REGISTER_BEAN;
        }
    }
    

    啊。基于注释的。那绝对是完美的。我忘记了注释,但是在SpringXML中有没有同样的方法呢。。。谷歌给了我一个看起来也可以做到的例子(尽管我不确定在那个例子中使用了哪个版本的Spring,因为它已经很旧了)