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

  • 相关阅读:
    1451. Rearrange Words in a Sentence
    1450. Number of Students Doing Homework at a Given Time
    1452. People Whose List of Favorite Companies Is Not a Subset of Another List
    1447. Simplified Fractions
    1446. Consecutive Characters
    1448. Count Good Nodes in Binary Tree
    709. To Lower Case
    211. Add and Search Word
    918. Maximum Sum Circular Subarray
    lua 时间戳和时间互转
  • 原文地址:https://www.cnblogs.com/aslanvon/p/15715102.html
Copyright © 2011-2022 走看看