Spring ecological study [five]: Springboot in bean conditions injection

In springboot, the developer does become a lot simpler, but now developers want to develop a fool-easy to get all kinds of strange project needs the best, do not burn the brain, had the program ape life is boring, do not adding give yourself more trouble.

 

Today, in order to facilitate this, the introduction, how to solve in the development process, in some scenarios, in order to achieve a configuration module, based on the switch or select configuration items, to achieve different functions, for example, in a session sharing module which, solving session is based on the header transfer or cookie-based delivery of these two scenarios, some applications based on header want to transfer sessionId, but some applications want cookie-based delivery sessionId, then, session sharing module, is a very basic components, almost i.e. a box with function block. So, it is best to configure, and then only need-based configuration file an option, you can achieve run under different operating modes. The ability to do it? Really only need to change it switch configuration can achieve it?

 

Can be achieved, secrecy here, I will not speak, introduced over after this post, the careful reader know the answer, or will be able to understand whether to do, how to do!

 

The first major point: first introduce springboot in support of or packaged condition commonly injected comment

1 @ConditionalOnBean

1.1 The basic use case

@Component
@ConditionalOnBean(name="aBean")
public class BBean {
  private final ABean aBean;
  public BBean(ABean aBean) {
      // ...
  }
}

 

1.2 instructions

Only when beang name for the time aBean existence, will inject BBean.

 

2 @ConditionalOnMissingBean

2.1 Basic Case

@Bean
@ConditionalOnMissingBean(name = "notExistsBean")
public BeanToCreate createOneBean() {
    return new BeanToCreate("notExistsBean");
}

 

2.2 instructions

Only when the bean name notExistsBean does not exist, BeanToCreate type of bean will be created, and use the opposite way @ConditionalOnBean

 

3 @ConditionalOnClass

3.1 The basic use case

@Bean
@ConditionalOnClass(DependedClz.class)
public InjectIfClzExists injectIfClzExists() {
    return new InjectIfClzExists("dependedClz");
}

 

3.2 instructions

Only when there is time for the Class of DependedClz.class, will inject InjectIfClzExists type of bean, and @ConditionalOnBean somewhat similar use.

 

4 @ConditionalOnMissingClass

4.1 Use Cases

@Bean
@ConditionalOnMissingClass("com.shihuc.bean.clz.DependedClz")
public InjectIfClzNotExists injectIfClzNotExists() {
    return new InjectIfClzNotExists("com.shihuc.bean.clz.DependedClz");
}

 

4.2 instructions

Only when there is no class com.shihuc.bean.clz.DependedClz time, it will inject InjectIfClzNotExists type of bean.

 

5 @ConditionalOnProperty

5.1 The basic use case

springboot project profiles application.properties file has the following configuration:

#.....
section.condition_field=noti
section.condition_property=test
#...
@Bean
@ConditionalOnProperty("section.condition_field")
public PropertyExistBean propertyExistBean() {
    return new PropertyExistBean("section.condition_field");
}

 

5.2 Instructions for use

Mainly based on the configuration parameters in the file to determine whether you need to create the bean, so that gave us a means to control the Bean selected in accordance with the configuration, this is very easy to use. This property exists because section.condition_field application.properties file, so, PropertyExistBean the bean will be created.

 

5.3 Extended Usage

5.3.1 comment defined

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty {

    /**
     * Alias for {@link #name()}.
     * @return the names
     * 注意,这个value和name不能同时使用
     */
    String[] value() default {};

    /**
     * A prefix that should be applied to each property. The prefix automatically ends
     * with a dot if not specified.
     * @return the prefix
     */
    String prefix() default "";

    /**
     * The name of the properties to test. If a prefix has been defined, it is applied to
     * compute the full key of each property. For instance if the prefix is
     * {@code app.config} and one value is {@code my-value}, the full key would be
     * {@code app.config.my-value}
     * <p>
     * Use the dashed notation to specify each property, that is all lower case with a "-"
     * to separate words (e.g. {@code my-long-property}).
     * @return the names
     */
    String[] name() default {};

    /**
     * The string representation of the expected value for the properties. If not
     * specified, the property must <strong>not</strong> be equal to {@code false}.
     * @return the expected value
     */
    String havingValue() default "";

    /**
     * Specify if the condition should match if the property is not set. Defaults to
     * {@code false}.
     * @return if should match if the property is missing
     */
    boolean matchIfMissing() default false;
}

 

When I want to achieve and the value of property aaa.bbb ccc their property when the configuration file exists before injection bean instance DDDD (named dddd).

@Bean("dddd")
@ConditionalOnProperty(value="aaa.bbbb", havingValue="ccc")
public DDDD propertyExistBean() {
    return new DDDD("aaa.bbb");
}

 

6 @ConditionalOnExpression

6.1 Use Cases

There are the following configuration content application.properties configuration file:

conditional.flag=true

java code corresponding to:

@Bean
@ConditionalOnExpression("#{'true'.equals(environment['conditional.flag'])}")
public ExpressTrueBean expressTrueBean() {
    return new ExpressTrueBean("express true");
}

 

6.2 instructions

Compared to the previous Bean, whether there is Class configuration parameters property if there is or there is some value in terms of this dependence SPEL expression, use it function even more powerful; it is mainly the implementation Spel expression, based on the return of true / false determining whether the condition.

 

The second major point: spring implanting bean-based interfaces and @Conditional notes Condition

This condition is equivalent to the root of bean injection solution, a customized version of the above-mentioned several other ConditionalOnXXXX notes, annotations, are the Conditional specific scene, if not able to meet their own scenarios, or to realize yourself a rather special conditions inject it, such as setting up of a number of conditions like, how to do it, then it would need to be achieved by the use of a condition-based interface @Conditional comment.

 

1 @Conditional annotation defines

//此注解可以标注在类和方法上
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
    /**
     * All {@link Condition}s that must {@linkplain Condition#matches match}
     * in order for the component to be registered.
     */
    Class<? extends Condition>[] value();
}

Note that this comment on a parameter value, and the parameter is an array of a Condition of Class.

 

2 Condition What is that?

@FunctionalInterface
public interface Condition {

    /**
     * Determine if the condition matches.
     * @param context the condition context
     * @param metadata metadata of the {@link org.springframework.core.type.AnnotationMetadata class}
     * or {@link org.springframework.core.type.MethodMetadata method} being checked
     * @return {@code true} if the condition matches and the component can be registered,
     * or {@code false} to veto the annotated component's registration
     */
    boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}

 

3. Use Cases

Suppose Properties file, there are two environmental parameters, temperature is a temp, a humidity Humi, only when the temperature is higher than 30 degrees, and the humidity is greater than 50 points, enable Linux, when the temperature is less than 30 degrees and a humidity of less than 50 when points, enabled Windows, this is just to illustrate a @Conditional in which multiple conditions are satisfied how to achieve, there are other business scenarios, you can refer to this case.

3.1 Configuration File Parameters

# Temperature data in degrees Celsius 
conditional.prop.temp = 29 
# humidity data, percentages herein without percent sign, corresponding to the expansion of 100 times, using time divided by 100 
conditional.prop.humi = 51 is

 

3.2 bean definitions

A HeWoBean interface implementation class and two HelloBean and WorldBean.

/**
 * @Author: chengsh05
 * @Date: 2019/8/29 16:17
 */
public interface HeWoBean {

    public String toString();
}
/**
 * @Author: chengsh05
 * @Date: 2019/8/29 15:52
 */
public class HelloBean implements HeWoBean {

    public String getHhh() {
        return hhh;
    }

    public void setHhh(String hhh) {
        this.hhh = hhh;
    }

    public String getEee() {
        return eee;
    }

    public void setEee(String eee) {
        this.eee = eee;
    }

    String hhh;

    String eee;

    public HelloBean(String hh, String ee) {
        this.hhh = hh;
        this.eee = ee;
    }

    @Override
    public String toString() {
        return this.hhh + ", " + this.eee;
    }
}
/**
 * @Author: chengsh05
 * @Date: 2019/8/29 15:54
 */
public class WorldBean implements HeWoBean {
    public String getWww() {
        return www;
    }

    public void setWww(String www) {
        this.www = www;
    }

    public String getOoo() {
        return ooo;
    }

    public void setOoo(String ooo) {
        this.ooo = ooo;
    }

    String www;
    String ooo;

    public WorldBean(String ww, String oo) {
        this.www = ww;
        this.ooo = oo;
    }

    @Override
    public String toString() {
        return this.www + ", " + this.ooo;
    }
}

 

3. condition and @Conditional application interface implementation class

/ * * 
 * @Author: chengsh05 
 * @date: 2019/8/29 9:08 
 * @Description: configuration information, the temperature and humidity conditions are satisfied when, i.e., when the temperature is greater than 30 degrees temp, humidity is greater than 50%, to enable linux 
 * / 
public  class LinuxTime the implements for condition Condition { 

    @Override 
    public Boolean The matches (ConditionContext context, AnnotatedTypeMetadata Metadata) { 
        String tempStr = Context.getEnvironment () getProperty (. " conditional.prop.temp " );
         a float TEMP = Float.valueOf (tempStr ); 
        String humiStr . Context.getEnvironment = () getProperty ( " conditional.prop.humi " );
         a float humi = Float.valueOf(humiStr);
        if(temp > 30 && humi > 60){
            return true;
        }
        return false;
    }
}
/ * * 
 * @Author: chengsh05 
 * @date: 2019/8/29 9:07 
 * @Description: configuration information, the temperature and humidity conditions are satisfied when, i.e., when the temperature is less than 30 degrees temp, humidity less than 50%, to enable Windows 
 * / 
public  class Windows Time {the implements for condition Condition 

    @Override 
    public Boolean The matches (ConditionContext context, AnnotatedTypeMetadata Metadata) { 
        String tempStr = Context.getEnvironment () getProperty (. " conditional.prop.temp " );
         a float TEMP = Float.valueOf (tempStr ); 
        String humiStr = Context.getEnvironment () getProperty (. " conditional.prop.humi " );
        float humi = Float.valueOf(humiStr);
        if(temp < 30 && humi < 60){
            return true;
        }
        return false;
    }
}
/**
 * @Author: chengsh05
 * @Date: 2019/8/29 15:50
 */
@Configuration
public class MyConditional {

    @Bean("mybean")
    @Conditional(LinuxTime.class)
    public HelloBean createHello() {
        return new HelloBean("hello", "Linux");
    }

    @Bean("mybean")
    @Conditional(WindowsTime.class)
    public WorldBean createWorld() {
        return new WorldBean("world", "Windows");
    }
}

 

4. The application verification

/**
 * @Author: chengsh05
 * @Date: 2019/8/29 16:03
 */
@Controller
@RequestMapping("/condition")
public class ConditionalController {

    @Autowired
    @Qualifier("mybean")
    private HeWoBean myBean;

    @RequestMapping("/check")
    @ResponseBody
    public void check() {
        System.out.println("///||||\\\\ ==> " + myBean.toString());
    }
}

Analysis point of view, LinuxTime because the temp and humidity humi temperature conditions (ie parameters in the configuration file) is not satisfied, so, LinuxTime this bean will not be created out of that final HeHoBean the only class in this configuration MyConditional WorldBean spring is injected into the container. The printed journal, also confirmed this.

///||||\\ ==> world, Windows

 

 

to sum up:

1. springboot built-in annotations conditions, develop some applications, a bean injection based on certain conditions is still very convenient, which can solve the most common scenarios based on demand.

2. The combination of injection-based annotation using the built-in conditions can be achieved with multiple constraints inject demand the bean, when injecting only a number of conditions are true, the corresponding spring bean will be injected into the container.

3. Built-in annotation does not work alone or in combination, can not get your application needs, you can choose to implement condition interfaces, based on @Conditional annotations to inject yourself condition needs.

 

Here, Tell me who, whether you have a conclusion, with regard to the aforementioned, session sharing module, based on configuration parameters switch, switch module flexible working header mode or cookie mode? The answer is yes, as to how to achieve, combined introduced me here, it is to get the answer.

 

Guess you like

Origin www.cnblogs.com/shihuc/p/11433062.html
Recommended