一、条件注解@Conditional,组合注解,元注解

1.

@Conditional:满足特定条件创建一个Bean,SpringBoot就是利用这个特性进行自动配置的。

例子:

首先,两个Condition,判断当前系统是否是Windows或者Linux(True False)

然后,2个ListService实现类,表明不同系统下的ListService实现。

主要,ConditionConfig使用了Java配置与@Conditional注解,根据LinuxCondition,或者WindowsCondition作为判断条件

产生相应与系统匹配的实现类。

最后,App.java 测试成功。

package com.springboot.springboot_test2_1;

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 arg0, AnnotatedTypeMetadata arg1) {
return arg0.getEnvironment().getProperty("os.name").contains("Linux");
} }

LinuxCondition.java

package com.springboot.springboot_test2_1;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata; public class WindowsCondition implements Condition { @Override
public boolean matches(ConditionContext arg0, AnnotatedTypeMetadata arg1) {
return arg0.getEnvironment().getProperty("os.name").contains("Windows");
} }

WindowsCondition.java

package com.springboot.springboot_test2_1;

public interface ListService {
public String showListCmd();
}

ListService.java

package com.springboot.springboot_test2_1;

public class LinuxListService implements ListService{

    @Override
public String showListCmd() {
return "ls";
} }

LinuxListService.java

package com.springboot.springboot_test2_1;

public class WindowsListService implements ListService{

    @Override
public String showListCmd() {
return "dir";
} }

WindowsListService.java

package com.springboot.springboot_test2_1;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration; @Configuration
public class ConditionConfig { @Bean
@Conditional(WindowsCondition.class)
public ListService windowsListService() {
return new WindowsListService();
} @Bean
@Conditional(LinuxCondition.class)
public ListService linuxListService() {
return new LinuxListService();
} }

ConditionConfig.java

package com.springboot.springboot_test2_1;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; /**
* Hello world!
*
*/
public class App {
public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(
ConditionConfig.class); ListService ls = context.getBean(ListService.class);
System.out.println(context.getEnvironment().getProperty("os.name")
+ "系统下的列表命令为:" + ls.showListCmd());
}
}

App.java

2.

元注解:可以注解到别的注解上的注解。

组合注解:元注解+被注解=组合注解。

例子:

package com.springboot.springboot_test2_1;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; @Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@ComponentScan
public @interface testConfig {
String[] value() default{};
}

testConfig.java

二、通过条件注解@Conditional,组合注解,元注解理解SpringBoot的自动配置

@SpringBootApplication,源码:

@Target({java.lang.annotation.ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters={@org.springframework.context.annotation.ComponentScan.Filter(type=org.springframework.context.annotation.FilterType.CUSTOM, classes={org.springframework.boot.context.TypeExcludeFilter.class}), @org.springframework.context.annotation.ComponentScan.Filter(type=org.springframework.context.annotation.FilterType.CUSTOM, classes={AutoConfigurationExcludeFilter.class})})
public @interface SpringBootApplication
{
@AliasFor(annotation=EnableAutoConfiguration.class, attribute="exclude")
Class<?>[] exclude() default {}; @AliasFor(annotation=EnableAutoConfiguration.class, attribute="excludeName")
String[] excludeName() default {}; @AliasFor(annotation=ComponentScan.class, attribute="basePackages")
String[] scanBasePackages() default {}; @AliasFor(annotation=ComponentScan.class, attribute="basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
}

SpringBootApplication源码

它的核心功能是由@EnableAutoConfiguration注解提供的,

@EnableAutoConfiguration,源码:

@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; /**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
Class<?>[] exclude() default {}; /**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
String[] excludeName() default {}; }

EnableAutoConfiguration源码

@EnableAutoConfiguration其中的@AutoConfigurationPackage,会扫描/META-INF/spring.factories文件中的jar包,

spring.factories文件如下:

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\

……

2、核心注解

spring.factories文件里每一个xxxAutoConfiguration文件一般都会有下面的条件注解:

@ConditionalOnBean:当容器里有指定Bean的条件下

@ConditionalOnClass:当类路径下有指定类的条件下

@ConditionalOnExpression:基于SpEL表达式作为判断条件

@ConditionalOnJava:基于JV版本作为判断条件

@ConditionalOnJndi:在JNDI存在的条件下差在指定的位置

@ConditionalOnMissingBean:当容器里没有指定Bean的情况下

@ConditionalOnMissingClass:当类路径下没有指定类的条件下

@ConditionalOnNotWebApplication:当前项目不是Web项目的条件下

@ConditionalOnProperty:指定的属性是否有指定的值

@ConditionalOnResource:类路径是否有指定的值

@ConditionalOnSingleCandidate:当指定Bean在容器中只有一个,或者虽然有多个但是指定首选Bean

@ConditionalOnWebApplication:当前项目是Web项目的条件下。

上面@ConditionalOnXXX都是组合@Conditional元注解,使用了不同的条件Condition

[读书笔记] 二、条件注解@Conditional,组合注解,元注解的更多相关文章

  1. Java开发笔记(八十二)注解的基本单元——元注解

    Java的注解非但是一种标记,还是一种特殊的类型,并且拥有专门的类型定义.前面介绍的五种内置注解,都可以找到对应的类型定义代码,例如查看注解@Override的源码,发现它的代码定义是下面这样的: @ ...

  2. spring揭秘 读书笔记 二 BeanFactory的对象注册与依赖绑定

    本文是王福强所著<<spring揭秘>>一书的读书笔记 我们前面就说过,Spring的IoC容器时一个IoC Service Provider,而且IoC Service Pr ...

  3. spring揭秘 读书笔记 二 BeanFactory的对象注冊与依赖绑定

    本文是王福强所著<<spring揭秘>>一书的读书笔记 我们前面就说过,Spring的IoC容器时一个IoC Service Provider,并且IoC Service Pr ...

  4. ES6读书笔记(二)

    前言 前段时间整理了ES6的读书笔记:<ES6读书笔记(一)>,现在为第二篇,本篇内容包括: 一.数组扩展 二.对象扩展 三.函数扩展 四.Set和Map数据结构 五.Reflect 本文 ...

  5. 《你必须知道的.NET》读书笔记二:小OO有大原则

    此篇已收录至<你必须知道的.Net>读书笔记目录贴,点击访问该目录可以获取更多内容. 一.单一职责原则 (1)核心思想:一个类最好只做一件事,只有一个引起它变化的原因 (2)常用模式:Fa ...

  6. Mastering Web Application Development with AngularJS 读书笔记(二)

    第一章笔记 (二) 一.scopes的层级和事件系统(the eventing system) 在层级中管理的scopes可以被用做事件总线.AngularJS 允许我们去传播已经命名的事件用一种有效 ...

  7. 【记】《.net之美》之读书笔记(二) C#中的泛型

    前言 上一篇读书笔记,很多小伙伴说这本书很不错,所以趁着国庆假期,继续我的读书之旅,来跟随书中作者一起温习并掌握第二章的内容吧. 一.理解泛型 1.为什么要使用泛型?-----通过使用泛型,可以极大地 ...

  8. how tomcat works 读书笔记(二)----------一个简单的servlet容器

    app1 (建议读者在看本章之前,先看how tomcat works 读书笔记(一)----------一个简单的web服务器 http://blog.csdn.net/dlf123321/arti ...

  9. java读书笔记二

    这是我的一些读书笔记: 我研究了一下面向对象: 面向对象符合人类看待事物的一般规律,对象的方法的实现细节是包装的,只有对象方法的实现者了解细节 我觉得面向过程是由过程.步骤.函数组成,过程是核心,面向 ...

随机推荐

  1. (转)spring学习之@ModelAttribute运用详解

    @ModelAttribute使用详解 1 @ModelAttribute注释方法 例子(1),(2),(3)类似,被@ModelAttribute注释的方法会在此controller每个方法执行前被 ...

  2. OPNET中FIN,FOUT以及FRET的作用 分类: opnet 2014-05-12 16:07 144人阅读 评论(0) 收藏

    为了使一个用户定义的函数被执行,该函数必须与一个特殊的堆栈跟踪代码相连.堆栈跟踪技术靠在函数的入口点和出口点插入预处理器宏指令完成(一个函数只有一个入口点,但可以有多个出口点(由C语言的return声 ...

  3. [BZOJ 3319] 黑白树

    3319: 黑白树 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 557  Solved: 194[Submit][Status][Discuss] ...

  4. 完整版百度地图点击列表定位到对应位置并有交互动画效果demo

    1.前言 将地图嵌入到项目中的需求很多,好吧,我一般都是用的百度地图.那么今天就主要写一个完整的demo.展示一个列表,点击列表的任一内容,在地图上定位到该位置,并有动画效果.来来来,直接上demo  ...

  5. mybatis入门介绍一

    首先介绍一下Mybatis是什么?mybatis是Java的持久层框架, JAVA操作数据库是通过jdbc来操作的,而mybatis是对jdbc的封装. 使用mybatis之后,开发者只需要关注sql ...

  6. error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏

    一.情形描述 下载了一个VS的源码,不知道此源码的版本.使用VS2010编译时出现如下报错: error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏 二.解决方法 在VS2010界 ...

  7. JavaScript字符串处理

    字符串处理 1.连接字符串: 1)连接符+: 2)连接赋值+=: 3)连接函concat() 2.查找子串位置indexOf() 1)在指定字符串中是否存在给定的字符串(第一次出现) 2)用法str. ...

  8. 如何编写轻量级 CSS 框架

    Github 地址: https://github.com/nzbin/snack Demo 演示: https://nzbin.github.io/snack/ 前言 这篇文章我已经酝酿了半年之久, ...

  9. H5入门——HTML部分

    一.HTML的基本构成 1.<!DOCTYPE html>文档类型声明 <!--HTML的文档类型声明.声明这个文件是HTML5文件,让浏览器按照HTML5准备进行解析显示.文档类型 ...

  10. Docker跨主机网络——overlay

    前言 在Docker网络--单host网络一文中,我为大家总结了Docker的单机网络相关知识和操作,单机网络比较容易.本文我为大家总结Docker跨主机通信相关知识.同样本文大部分内容以CloudM ...