Spring扩展------基于`@Conditional`注解以及`Condition`接口的扩展

@Conditional注解是spring在4.0版本提供的一个注解,作用是贴有这个注解或间接贴有的bean在满足指定的Condition接口实现类的matches方法校验之后,才注册这个bean。关于@Conditional注解的实现原理,可以看看前面写的一篇文章。@Conditional注解的解析

1. 直接使用@Conditional注解
1.1 定义一个Bean,并在上面贴上@Conditional注解
public class ConditionalTestBootstrap {
	@Bean
	@Conditional(MyCondition.class)
	public String conditionTest(){
		return "condition test";
	}	
}

 如上面的代码所示,直接使用@Conditional注解的方式。使用这个注解的前提要求是:这个对象需要是一个被容器管理的对象。

1.2 @Conditional注解指定的类实现Condition接口

 上面的@Conditional注解中指定的类是MyCondition。因此这个类需要实现Condition接口

public class MyCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        Map<String, Object> attributes = annotatedTypeMetadata.getAnnotationAttributes(Conditional.class.getName());
        Object value = attributes.get("value");
        if (value!=null){
            System.out.println("当校验条件为true的时候,返回true");
            return true;
        }else {
            System.out.println("当校验条件为false的时候,返回false");
            return false;
        }
    }
}

 在实现的matches方法中,可以自行定义判断逻辑,从AnnotatedTypeMetadata中可以获取贴有注解信息的对象或者方法的很多信息,可以利用这些信息来进行逻辑判断。
 当最终结果返回为true的时候,就表示校验符合,就会将bean进行注册。

1.3 在启动类中进行校验
public class ConditionalTestBootstrap {
	public static void main(String[] args) {
		ConfigurableApplicationContext applicationContext = new SpringApplicationBuilder(ConditionalTestBootstrap .class)
				.web(WebApplicationType.NONE)
				.run(args);
		String conditionTest = applicationContext.getBean("conditionTest", String.class);
		System.out.println("conditionTest Bean "+conditionTest);
		//关闭上下文
		applicationContext.close();
	}
}

 最终的运行结果为conditionTest Bean condition test。此时说明这个bean成功的被注入到了容器之中。
 当我们把上面实现的matches方法中返回的结果改为false的时候再试试

public class MyCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
       return false;
    }
}

此时运行结果为

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'conditionTest' available
	at 
	......

 最后运行出错了,因为容器中没有名称为conditionTest的bean

2. 间接使用@Conditional注解

 因为spring原生提供的@Conditional注解内部只有一个value属性用来指定我们匹配规则的类,没有其余的属性供我们使用。所以通常都是对@Conditional注解进行派生使用。

2.1 定义一个@Conditional注解的派生注解
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnSystemPropertyCondition.class)
public @interface ConditionalOnSystemProperty {
	/**
	 * java 系统属性名称
	 * @return
	 */
	String name() default "";

	/**
	 * java系统属性值
	 * @return
	 */
	String value() default "";
}

 定义@Conditional的派生注解,通常是在自定义的注解上加上一个@Conditional注解并指定实现匹配规则的Condition接口的实现类。

2.2 实现Condition接口处理
public class OnSystemPropertyCondition implements Condition {
	@Override
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		Map<String, Object> attributes = metadata.getAnnotationAttributes(ConditionalOnSystemProperty.class.getName());
		String propertyName = String.valueOf(attributes.get("name"));
		String propertyValue = String.valueOf(attributes.get("value"));
		String javaProperty = System.getProperty(propertyName);
		return propertyValue.equals(javaProperty);
	}
}

 上面就是自定义的判定逻辑。从AnnotatedTypeMetadata中获取ConditionalOnSystemProperty类型的注解,然后获取到注解内的属性值。然后比较来决定匹配结果。

2.3 在bean上面使用自定义的注解
public class ConditionalOnSystemPropertyBootstrap {
	@Bean
	@ConditionalOnSystemProperty(name = "user.name",value = "Administrator")
	public String helloWorld(){
		return "hello world szh";
	}
}

 在定义的bean上面加上自定义的@ConditionalOnSystemProperty注解,并添加上对应的条件。

2.4 在启动类中校验
public class ConditionalOnSystemPropertyBootstrap {
	public static void main(String[] args) {
		ConfigurableApplicationContext applicationContext = new SpringApplicationBuilder(ConditionalOnSystemPropertyBootstrap.class)
				.web(WebApplicationType.NONE)
				.run(args);
		String helloWorld = applicationContext.getBean("helloWorld", String.class);
		System.out.println("helloWorld Bean "+helloWorld);
		//关闭上下文
		applicationContext.close();
	}
}

 最后的运行结果为helloWorld Bean hello world szh。说明我们的bean成功的注入到了容器中。到这里@Conditional注解以及Condition接口的扩展就完了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值