zoukankan      html  css  js  c++  java
  • Spring 之容器注册组件

    概述

    给容器中注册组件一共有 4 种方法

    1. 包扫描+组件标注注解
      @Controller/@Service/@Repository/@Component)[自己写的类]
    2. @Bean[导入的第三方包里面的组件]
    3. @Import[快速给容器中导入一个组件]
      1. @Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名
      2. ImportSelector:返回需要导入的组件的全类名数组;
      3. ImportBeanDefinitionRegistrar:手动注册bean到容器中
    4. 使用Spring提供的 FactoryBean(工厂Bean);
      1. 默认获取到的是工厂bean调用getObject创建的对象
      2. 要获取工厂Bean本身,我们需要给id前面加一个&
        &colorFactoryBean

    一、@Configuration @Bean 给容器注册组件

    传统的 XML 配置方式

    在src 下定义类 Person
    public class Person {
    
        private String name;
        private Integer age;
    
        // 省略无参构造,有参构造,getter/setter,toString 方法
    }
    
    resource/beans.xml 里定义 bean
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
        <bean id="person" class="cn.duniqb.bean.Person">
            <property name="age" value="18"/>
            <property name="name" value="zs"/>
        </bean>
    </beans>
    
    测试
    public class MainTest {
    
        public static void main(String[] args) {
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
            Person person = (Person) applicationContext.getBean("person");
            System.out.println(person);
        }
    }
    
    输出
    Person{name='zs', age=18}
    

    使用配置类

    创建配置类

    使用 @Bean 注解,可以显式地指定 id

    /**
     * 配置类等同于配置文件
     * 标识这是一个配置类
     */
    @Configuration
    public class MainConfig {
        /**
         * 给容器注册一个 Bean
         * @return 类型是返回值的类型,id 默认用方法名为 id
         */
        @Bean("person")
        public Person person01() {
            return new Person("ls", 20);
        }
    }
    
    测试
    public class MainTest {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
            Person bean = applicationContext.getBean(Person.class);
            System.out.println(bean);
            // 查看 bean 的id
            String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
            for (String s : namesForType) {
                System.out.println(s);
            }
        }
    }
    
    输出
    Person{name='ls', age=20}
    person
    

    二、组件扫描 @ComponentScan

    以下会扫描出在 cn.duniqb 下的所有类

    /**
     * 配置类等同于配置文件
     * 标识这是一个配置类
     */
    @Configuration
    @ComponentScan(value = "cn.duniqb")
    public class MainConfig {
    
        /**
         * 给容器注册一个 Bean
         *
         * @return 类型是返回值的类型,id 默认用方法名为 id
         */
        @Bean("person")
        public Person person01() {
            return new Person("ls", 20);
        }
    }
    
    排除指定注解

    指定扫描的时候按照什么规则排除那些组件,默认是空

    Filter[] excludeFilters() default {};
    

    以下会排除带有 @Controller 与 @Service 的组件

    @Configuration
    @ComponentScan(value = "cn.duniqb", excludeFilters = {
            @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class})
    })
    public class MainConfig {
    
        /**
         * 给容器注册一个 Bean
         *
         * @return 类型是返回值的类型,id 默认用方法名为 id
         */
        @Bean("person")
        public Person person01() {
            return new Person("ls", 20);
        }
    }
    
    包含指定注解
    @Configuration
    @ComponentScan(value = "cn.duniqb", includeFilters = {
            @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
    }, useDefaultFilters = false)
    public class MainConfig {
        /**
         * 给容器注册一个 Bean
         *
         * @return 类型是返回值的类型,id 默认用方法名为 id
         */
        @Bean("person")
        public Person person01() {
            return new Person("ls", 20);
        }
    }
    

    三、@Scope 设置组件作用域

    通过源码看出,Scope 有 4 个取值,分别是多实例,单实例,Web 环境下的单请求,Web 环境下的Session

    单实例是默认值, ioc 容器会启动调用方法创建对象放到 ioc 容器中,以后每次获取都是从容器中拿取。

    多实例时,每次获取时候才会调用方法创建对象。

    /**
     * Specifies the name of the scope to use for the annotated component/bean.
     * <p>Defaults to an empty string ({@code ""}) which implies
     * {@link ConfigurableBeanFactory#SCOPE_SINGLETON SCOPE_SINGLETON}.
     * @since 4.2
     * @see ConfigurableBeanFactory#SCOPE_PROTOTYPE
     * @see ConfigurableBeanFactory#SCOPE_SINGLETON
     * @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST
     * @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION
     * @see #value
     */
    @AliasFor("value")
    String scopeName() default "";
    
    默认是是单实例的
    @Configuration
    public class MainConfig2 {
        @Scope
        @Bean("person")
        public Person person() {
            return new Person("zs", 25);
        }
    }
    
    添加后是多实例
    @Configuration
    public class MainConfig2 {
        @Scope("prototype")
        @Bean("person")
        public Person person() {
            return new Person("zs", 25);
        }
    }
    

    懒加载 @Lazy

    单实例 bean,默认在容器启动时创建对象,懒加载是容器启动时不创建对象,在第一次获取时创建对象,并初始化,此时还是单实例。

    @Configuration
    public class MainConfig2 {
        @Scope("prototype")
        @Bean("person")
        @Lazy
        public Person person() {
            return new Person("zs", 25);
        }
    }
    

    四、按条件注册@Conditional

    /**
     * Conditional
     * @return
     */
    @Conditional({WindowsCondition.class})
    @Bean("bill")
    public Person person01() {
        return new Person("Bill Gates", 62);
    }
    

    只有下面情况 true 时才会加载

    public class WindowsCondition implements Condition {
        @Override
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    
            Environment environment = context.getEnvironment();
    
            String property = environment.getProperty("os.name");
            if (property.contains("Windows")) {
                return true;
            }
    
            return false;
        }
    }
    

    快速导入 @Import

    在配置类上加注解即可实现注册

    @Configuration
    @Import(Color.class)
    public class MainConfig2 {
    
    }
    

    没有修不好的电脑
  • 相关阅读:
    每周分享五个 PyCharm 使用技巧(一)
    深入理解 Python 中的上下文管理器
    Delphi中Chrome Chromium、Cef3学习笔记(四)
    DELPHI中自定义消息的发送和接收
    Delphi2010/XE2下隐藏程序系统任务栏的图标
    批处理经典入门教程!(从不懂到高手)第2/5页
    批处理经典入门教程!(从不懂到高手)1/5
    批处理taskkill运行结束不掉程序以及停留问题
    delphi EncdDecd.pas单元中Encoding方法出现#$D#$A的解决方法
    Delphi中Chrome Chromium、Cef3学习笔记(三)
  • 原文地址:https://www.cnblogs.com/duniqb/p/12702442.html
Copyright © 2011-2022 走看看