好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

spring @Conditional的使用与扩展源码分析

@Conditional的使用

@Conditional可以根据条件来判断是否注入某些Bean。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

package com.morris.spring.config;

 

import com.morris.spring.condition.LinuxCondition;

import com.morris.spring.condition.WindowsCondition;

import com.morris.spring.entity.User;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Conditional;

import org.springframework.context.annotation.Configuration;

@Configuration

public class ConditionalConfig {

     // 如果是windows系统就注入bill

     @Conditional (WindowsCondition. class )

     @Bean (name = "user" )

     public User bill() {

         return new User( "bill" , 22 );

     }

     // 如果是linux系统就注入linus

     @Conditional (LinuxCondition. class )

     public User linus() {

         return new User( "linus" , 20 );

}

WindowsCondition和LinuxCondition都需要实现Condition接口。

WindowsCondition

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

package com.morris.spring.condition;

 

import org.springframework.context.annotation.Condition;

import org.springframework.context.annotation.ConditionContext;

import org.springframework.core.type.AnnotatedTypeMetadata;

public class WindowsCondition implements Condition {

     /**

      * 根据条件判断是否注入对应的Bean

      * @param conditionContext 应用上下文

      * @param annotatedTypeMetadata 加了@Conditional注解的方法的元数据信息

      * @return

      */

     @Override

     public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {

         String osName = conditionContext.getEnvironment().getProperty( "os.name" );

         if (osName.contains( "Windows" )) {

             return true ;

         }

         return false ;

     }

}

LinuxCondition

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

package com.morris.spring.condition;

 

import org.springframework.context.annotation.Condition;

import org.springframework.context.annotation.ConditionContext;

import org.springframework.core.type.AnnotatedTypeMetadata;

public class LinuxCondition implements Condition {

     @Override

     public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {

         String osName = conditionContext.getEnvironment().getProperty( "os.name" );

         if (osName.contains( "linux" )) {

             return true ;

         }

         return false ;

     }

}

如果要测试LinuxCondition并不需要再linux系统下运行,只需要的启动时设置环境参数: -Dos.name=linux 。

Conditional的扩展

ConditionalOnBean

ConditionalOnBeanc.java

?

1

2

3

4

5

6

7

8

9

10

11

package com.morris.spring.condition;

 

import org.springframework.context.annotation.Conditional;

import java.lang.annotation.*;

@Target ({ElementType.TYPE, ElementType.METHOD})

@Retention (RetentionPolicy.RUNTIME)

@Documented

@Conditional (OnBeanCondition. class )

public @interface ConditionalOnBean {

     Class<?>[] value() default {};

}

OnBeanCondition.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

package com.morris.spring.condition;

 

import org.springframework.context.annotation.Condition;

import org.springframework.context.annotation.ConditionContext;

import org.springframework.core.type.AnnotatedTypeMetadata;

import java.util.Map;

public class OnBeanCondition implements Condition {

     @Override

     public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {

         Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(ConditionalOnBean. class .getName());

         Class<?>[] clazz = (Class<?>[]) annotationAttributes.get( "value" );

         for (Class<?> aClass : clazz) {

             Map<String, ?> beans = context.getBeanFactory().getBeansOfType(aClass);

             if (beans.isEmpty()) {

                 return false ;

             }

         }

         return true ;

     }

}

ConditionalOnProperty

ConditionalOnProperty.java

?

1

2

3

4

5

6

7

8

9

10

11

package com.morris.spring.condition;

 

import org.springframework.context.annotation.Conditional;

import java.lang.annotation.*;

@Target ({ElementType.TYPE, ElementType.METHOD})

@Retention (RetentionPolicy.RUNTIME)

@Documented

@Conditional (OnPropertyCondition. class )

public @interface ConditionalOnProperty {

     String[] value() default {};

}

OnPropertyCondition.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

package com.morris.spring.condition;

 

import org.springframework.context.annotation.Condition;

import org.springframework.context.annotation.ConditionContext;

import org.springframework.core.type.AnnotatedTypeMetadata;

import java.util.Map;

public class OnPropertyCondition implements Condition {

     @Override

     public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {

         Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(ConditionalOnProperty. class .getName());

         String[] propertyArray = (String[]) annotationAttributes.get( "value" );

         for (String property : propertyArray) {

             if (!context.getEnvironment().containsProperty(property)) {

                 return false ;

             }

         }

         return true ;

     }

}

源码分析

如果Condition返回的是false,那么spirng就不会对方法或类进行解析。

org.springframework.context.annotation.ConditionEvaluator#shouldSkip

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

public boolean shouldSkip( @Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {

     // 判断类或方法上面是否有@Conditional注解

     if (metadata == null || !metadata.isAnnotated(Conditional. class .getName())) {

         return false ;

     }

     if (phase == null ) {

         if (metadata instanceof AnnotationMetadata &&

                 ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {

             return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);

         }

         return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);

     List<Condition> conditions = new ArrayList<>();

     for (String[] conditionClasses : getConditionClasses(metadata)) {

         for (String conditionClass : conditionClasses) {

             Condition condition = getCondition(conditionClass, this .context.getClassLoader());

             conditions.add(condition);

     AnnotationAwareOrderComparator.sort(conditions);

     for (Condition condition : conditions) {

         ConfigurationPhase requiredPhase = null ;

         if (condition instanceof ConfigurationCondition) {

             requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();

         // 调用condition.matches方法

         if ((requiredPhase == null || requiredPhase == phase) && !condition.matches( this .context, metadata)) {

             return true ;

     return false ;

}

到此这篇关于spring @Conditional的使用与扩展的文章就介绍到这了,更多相关spring @Conditional使用内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

原文链接:https://blog.csdn.net/u022812849/article/details/123729369

查看更多关于spring @Conditional的使用与扩展源码分析的详细内容...

  阅读:19次