• Bean装配相关注解使用说明


    @ComponentScan

    • 启用组件扫描
    • 默认扫描与配置类相同的包以及子包

    如何扫描指定的包

    • @ComponentScan(“包名”)
    • 扫描一组包: @ComponentScan(basePackages={"xxx","xxx"})

    这种两种方式都是传入字符串,无法方便的重构。因为我们的编辑器一般不会解析你的字符串值,可以使用下面方式:

    • 扫描类和接口: @ComponentScan(basePackageClasses={xxx.class, xxxx.class}) 这些类所在的包会作为组件扫描的基础包,可以为需要扫描的包中添加一个空接口,标记该包需要扫描,这种方式避免了传入字符串,方便重构修改

    @ContextConfiguration(classes=xxx.class)

    需要在 xxx.class 中加载配置

    @Component

    向容器中注册组件

    • bean 的名字默认是类名首字母小写
    • 也可以指定: @Component(“xxx”)
    • @Named 可以替代 @Component

    @Autowired

    • 用在构造器上 当 Spring 去创建该类的 bean 时,会调用这个构造方法,同时传入一个 满足参数的 bean

      Class User {
          private Car car;
         // 会使用这个方法去构造 bean, 而不是无    参构造器
          @Autowired
          public User(Car car){
              this.car = car;
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
    • 用在 Setter 方法上

    • 其实可以用在类的任何方法上,Spring 尝试满足方法参数上声明的依赖,如果找不到对应的 bean 就会抛出异常

    • @Autowired(required=false) 即使没找到也不会抛出异常,会传入 Null. 可能会导致空指针异常

    • 如果有多个 bean 都能满足,会抛出异常

    • 可以使用 Inject 替换,Inject 是 java 中依赖注入规范

    @Bean

    • 显示配置 Bean, 可以把第三方对象设置成 Bean,因为我们无法直接在第三方类上添加@Component 注解
    • bean Id 默认是方法名,可以指定:@Bean("xxx")
      @Configuration
      @ComponentScan
      public class AutowiredDemoConfig {
          /**
          * User 是引入的第三方工具,无法修改 User 类,在类名上加 @Component 注解
          */
      
          @Bean
          public User user(){
              return new User(10,"dc1");
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12

    @Profile(“dev”)

    • 和@Bean 一起使用,当 dev 环境上才会创建 bean
    • 配置
      spring.profiles.default=dev 或者 spring.profiles.active=dev 激活 dev 环境,如果没有激活的环境,只会创建那些没有定义在 profile 中的 bean
    • 从 Spring 4 开始,依赖 @Conditional 注解

    @Conditional

    • Since 4.0
    • 条件化的 bean
    • 用到带有@Bean 的注解的方法上
    • 给定条件的结果为 true 时,创建 bean 否则不创建
    • 需要实现 Conditional 接口中的 matches 方法

    @Primary

    • 处理自动装配的歧义

    • 如果一个 Bean 是接口,系统中有多个实现类。注入时就会有歧义,抛出异常

    • @Primary 用在 Bean 上,标记这个 bean 是首选的,发生歧义时首选它, 不会报错

    • 缺点: 只能使用其中一个 bean,无法指定注入哪个,@Qualifier 解决这个问题

      示例:

      @RunWith(SpringJUnit4ClassRunner.class)
      @ContextConfiguration(classes = AutowiredDemoConfig.class)
      public class QualifierDemo {
        @Autowired
        private Dessert dessert;
      
        @Test
        public void eat(){
            dessert.getName();
        }
      
      }
      
      /**
      * Cake IceCream 都实现了 Dessert
      */
      interface Dessert{
        String getName();
      }
      
      @Component
      @Primary // 会优先注入 Cake
      class Cake implements Dessert {
        public String getName() {
            String name = "Cake";
            System.out.println(name);
            return name;
        }
      }
      
      @Component
      class IceCream implements Dessert{
      
        public String getName() {
            String name = "IceCream";
            System.out.println(name);
            return name;
        }
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40

    @Qualifier(“xxx bean name”)

    • 与 @Autowired 一起使用时直接指定 bean 的名字进行装配:
    • 与 @Component 一起使用,可以设置 bean 的名字
    • 与 @Bean 一起使用,可以设置 bean 的名字

    @Scope bean 的作用域

    默认所有的 bean 都是单例的。Spring 定义了多种作用域,包括:

    • 单例 (Singleton): 整个应用中只创建一个 bean 实例
    • 原型 (Prototype): 每次注入或者通过 Spring 应用上下文获取的时候,都会创建一个新的 bean。
    • 会话 (Session): 在 Web 应用中,为每个会话创建一个实例
    • 请求 (Request): 在 Web 应用中,为每个请求创建一个实例

    示例

    使用 @Scope 注解,改变bean的作用域

    @RunWith(SpringJUnit4ClassRunner.class)
    @ComponentScan
    @ContextConfiguration(classes = ScopeDemo.class)
    public class ScopeDemo {
        @Autowired
        @Qualifier("singleSTU")
        private Student s1;
    
        @Autowired
        @Qualifier("singleSTU")
        private Student s2;
    
        @Autowired
        @Qualifier("prototypeSTU")
        private Student s3;
    
        @Autowired
        @Qualifier("prototypeSTU")
        private Student s4;
    
        @Test
        public  void scopeDemo(){
            Assert.assertEquals("s1 s2 是单例作用域,两者应该相等:", s1.hashCode(), s2.hashCode());
            Assert.assertNotEquals("s3 s4 是原型作用域,两者应该不相等:", s3.hashCode(), s4.hashCode());
        }
    }
    
    @Configuration
    class Student {
    
        private int age;
    
        /**
         * 默认是单例作用域
         * @return
         */
        @Bean("singleSTU")
        public Student stu(){
            Random random = new Random();
            Student s1 = new Student();
            s1.setAge(random.nextInt(100));
            return s1;
        }
    
        /**
         * 设置原型作用域
         * @return
         */
        @Bean("prototypeSTU")
        @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
        public Student stu1(){
            Random random = new Random();
            Student s1 = new Student();
            s1.setAge(random.nextInt(100));
            return s1;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    运行时注入外部值

    把配置文件中的字段注入到对象中

    Enviroment

    通过注解@PropertySource(“xxx”)讲配置文件中的信息注入到Enviorment 对象中:

    @RunWith(SpringJUnit4ClassRunner.class)
    @ComponentScan
    @ContextConfiguration(classes = EnviromentDemo.class)
    public class EnviromentDemo {
    
        @Autowired
        private Mysql mysql;
    
        @Test
        public void testDataSource(){
            System.out.println(mysql.getPort());
        }
    
    }
    
    @Configuration
    @PropertySource("classpath:/app.properties")// 将配置文件中的字段加载到 Environment 中,稍后可以通过 Environment 对象获取
    class DataSource {
    
        @Autowired
        Environment env;
    
        @Bean
        public Mysql mysql(){
            // 获取对应的字段值,getProperty 更多用法参考源码
            return  new Mysql(env.getProperty("mysql.port", Integer.class), env.getProperty("mysql.host"));
    
        }
    }
     class Mysql {
         private int port;
         private String host;
    
         public Mysql(int port, String host) {
             this.port = port;
             this.host = host;
         }
    
         public int getPort() {
             return port;
         }
    
         public void setPort(int port) {
             this.port = port;
         }
    
         public String getHost() {
             return host;
         }
    
         public void setHost(String host) {
             this.host = host;
         }
     }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    通过属性占位符装配

    还可以通过 ${} 占位符读取配置文件中的字段,注入到字段中; 如下:

    @RunWith(SpringJUnit4ClassRunner.class)
    @ComponentScan
    @ContextConfiguration(classes = ValueDemo.class)
    public class ValueDemo {
    
        @Autowired
        private Mysql1 mysql;
    
        @Test
        public void testDataSource(){
            System.out.println(mysql.getPort());
        }
    
    }
    
    @Configuration
    class DataSource1 {
    
        @Autowired
        Environment env;
    
        @Bean // 这个bean 是必须的。可以解析占位符,自动查找
        public  static PropertySourcesPlaceholderConfigurer  propertySourcesPlaceholderConfigurer(){
            return new PropertySourcesPlaceholderConfigurer();
        }
    
        @Bean
        // ${} 占位符方式注入
        public Mysql1 mysql(@Value("${mysql.port}") int port,@Value("${mysql.host}") String host){
            // 获取对应的字段值,getProperty 更多用法参考源码
            return  new Mysql1(port, host);
    
        }
    }
    
    class Mysql1 {
        private int port;
        private String host;
    
        public Mysql1(int port, String host) {
            this.port = port;
            this.host = host;
        }
    
        public int getPort() {
            return port;
        }
    
        public void setPort(int port) {
            this.port = port;
        }
    
        public String getHost() {
            return host;
        }
    
        public void setHost(String host) {
            this.host = host;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
  • 相关阅读:
    使用html+css+js实现一个静态页面(含源码)
    java-php-python-医院挂号系统计算机毕业设计
    10-类加载器
    方波信号发生器电路仿真,小波神经网络算法原理
    C++入门笔记
    SSM出租车查询系统毕业设计-附源码220915
    基于小程序探索如何实现数字传媒内容价值最大化
    【Kotlin精简】第2章 集合
    word2vec和bert的基本使用方法
    WorkManager 一篇文章就够了
  • 原文地址:https://blog.csdn.net/a141210104/article/details/127655567