zoukankan      html  css  js  c++  java
  • Springboot笔记<3> 组件注入注解@Conditional与@import

    @Conditional

    @Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件给容器注册bean。

    创建ConfigConditional类和测试类ConfigConditionalTest

    @Configuration
    public class ConfigConditional {
        @Bean(name = "xiaoming")
        public Student getStudent1(){
            Student student = new Student();
            student.setName("xiaoming");
            student.setAge(18);
            return student;
        }
        @Bean(name = "xiaohong")
        public Student getStudent2(){
            Student student = new Student();
            student.setName("xiaohong");
            student.setAge(17);
            return student;
        }
    }
    

    测试类ConfigConditionalTest

    输出结果为{xiaoming=Student(age=18, name=xiaoming), xiaohong=Student(age=17, name=xiaohong)},说明两个Student实例被注入进容器。

    public class ConfigConditionalTest {
    
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ConfigConditional.class);
    
        @Test
        public void test1() {
            Map<String, Student> map = applicationContext.getBeansOfType(Student.class);
            System.out.println(map);
        }
    }
    //输出为{xiaoming=Student(age=18, name=xiaoming), xiaohong=Student(age=17, name=xiaohong)}
    

    如果我想根据当前操作系统来注入Student实例,只有在非windows操作系统的情况下注入xiaoming。

    这就需要我们用到@Conditional注解了。

    @Conditional作用

    Class<? extends Condition>[] value()说明@Conditional注解传入的是一个Class数组,存在多种条件类的情况。@Target({ElementType.TYPE, ElementType.METHOD})说明@Conditional可以作用在方法和类上,一个方法只能注入一个bean实例,所以@Conditional标注在方法上只能控制一个bean实例是否注入。标注在类上:一个类中可以注入很多实例,@Conditional标注在类上就决定了一批bean是否注入。

    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Conditional {
       /**
        * All {@link Condition} classes that must {@linkplain Condition#matches match}
        * in order for the component to be registered.
        */
       Class<? extends Condition>[] value();
    
    }
    

    @Conditional举例

    创建WindowsConfig,非windows系统,返回true。

    public class WindowsConfig implements Condition {
    
        @Override
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
            //获取ioc使用的beanFactory
            ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
            //获取类加载器
            ClassLoader classLoader = context.getClassLoader();
            //获取当前环境信息
            Environment environment = context.getEnvironment();
            //获取bean定义的注册类
            BeanDefinitionRegistry registry = context.getRegistry();
            //获得当前系统名
            String property = environment.getProperty("os.name");
            //不包含Windows则说明不是windows系统,返回true
            if (!property.contains("Windows")) {
                return true;
            }
            return false;
        }
    }
    

    @Conditional作用在方法上

    @Configuration
    public class ConfigConditional {
        @Bean(name = "xiaoming")
        @Conditional(WindowsConfig.class)
        public Student getStudent1(){
            Student student = new Student();
            student.setName("xiaoming");
            student.setAge(18);
            return student;
        }
        @Bean(name = "xiaohong")
        public Student getStudent2(){
            Student student = new Student();
            student.setName("xiaohong");
            student.setAge(17);
            return student;
        }
    }
    

    因为只在非windows系统注入xiaoming,因此输出为{xiaohong=Student(age=17, name=xiaohong)}。

    @Conditional作用在类上

    @Configuration
    @Conditional(WindowsConfig.class)
    public class ConfigConditional {
        @Bean(name = "xiaoming")
        public Student getStudent1(){
            Student student = new Student();
            student.setName("xiaoming");
            student.setAge(18);
            return student;
        }
        @Bean(name = "xiaohong")
        public Student getStudent2(){
            Student student = new Student();
            student.setName("xiaohong");
            student.setAge(17);
            return student;
        }
    }
    

    因为只在非windows系统注入xiaoming和xiaohong,因此输出为{}

    @import

    @Import注解用来帮助我们把一些需要定义为Bean的类导入到IOC容器里面。如果配置类在标准的springboot的包结构下,就是SpringbootApplication启动类在包的根目录下,配置类在子包下。就不需要使用@Import导入配置类,如果配置类在第三方的jar下,我们想要引入这个配置类,就需要@Import对其引入到工程中才能生效。因为这个时候配置类不再springboot默认的扫描范围内。

    @Import源码注释里可以知道,value里面传递的Class会被Spring识别成为component组件。

    @Import源码注释里面的一段说明,指出了@Import的用法

    1. 导入一个@Configuration类
    2. 导入ImportSelector,ImportBeanDefinitionRegistrar的实现类
    3. 导入一个普通的类
     /* 
     *<p>Provides functionality equivalent to the {@code <import/>} element in Spring XML.
     * Allows for importing {@code @Configuration} classes, {@link ImportSelector} and
     * {@link ImportBeanDefinitionRegistrar} implementations, as well as regular component
     * classes (as of 4.2; analogous to {@link AnnotationConfigApplicationContext#register}).
     */
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Import {
    
       /**
        * {@link Configuration @Configuration}, {@link ImportSelector},
        * {@link ImportBeanDefinitionRegistrar}, or regular component classes to import.
        */
       Class<?>[] value();
    
    }
    

    @Import引入普通类

    @Import引入普通的类可以帮助我们把普通的类定义为Bean。@Import可以添加在@SpringBootApplication(启动类)、@Configuration(配置类)、@Component(组件类)对应的类上。

    定义Teacher类

    @Data
    public class Teacher {
        private int age;
        private String name;
    }
    

    在springboot的启动类@Import Teacher类,这个类就可以被其他类当做bean来引用。

    输出结果Teacher(age=0, name=null)

    @SpringBootApplication
    @Import({Teacher.class})
    public class SpringbootReviewApplication {
    
        public static void main(String[] args) {
            ConfigurableApplicationContext run = SpringApplication.run(SpringbootReviewApplication.class, args);
            Teacher teacher = run.getBean(Teacher.class);
            System.out.println(teacher);
        }
    }
    //输出结果Teacher(age=0, name=null)
    

    @Import引入配置类(@Configuration修饰的类)

    @Import除了可以把普通的类定义为Bean,@Import还可以引入一个@Configuration修饰的类(引入配置类),从而把让配置类生效(配置类下的所有Bean添加到IOC容器里面去)如果配置类在标准的SpringBoot包结构下(SpringBootApplication启动类包的根目录下)。是不需要@Import导入配置类的,SpringBoot自动帮做了。上面的情况一般用于@Configuration配置类不在标准的SpringBoot包结构下面。所以一般在自定义starter的时候用到。

    public class ImportDemo {
        public void doSomething () {
            System.out.println("ImportDemo.doSomething()");
        }
    }
     
    @Configuration
    @Import({ImportDemo.class})
    public class ImportConfig{
    @Bean
        public Student returnOneStudent(){
            return new Student();
        }
    }
     
    @RestController
    public class ImportDemoController {
     
        @Autowired
        private Student student;
     
        @Autowired
        private ImportDemo importDemo;
     
        @RequestMapping("/importDemo")
        public String demo() throws Exception {
            importDemo.doSomething();
            return "ImportDemo" + student.toString;
        }
    }
    

    未经作者同意请勿转载

    本文来自博客园作者:aixueforever,原文链接:https://www.cnblogs.com/aslanvon/p/15715102.html

  • 相关阅读:
    WPF分页控件
    Anroid图标尺寸
    linux常用快捷键
    securecrt中vim行号下划线问题及SecureCRT里root没有高亮的设置,修改linux终端命令行颜色
    ANT-普通替换和正则替换
    js实现IOS上删除app时颤抖动画j函数
    php语法错误导致服务器错误(500)解决
    Linux 常用命令大全2
    Linux 命令行快捷键
    backbone源代码注释(部分)
  • 原文地址:https://www.cnblogs.com/aslanvon/p/15715102.html
Copyright © 2011-2022 走看看