05-SpringBoot-bean管理

Bean扫描

  • 标签

    <context:component-scan base-package="com.lxx"/>
    
  • 注解

    @ComponentScan(basePackages = "com.lxx")
    

    05-SpringBoot-bean管理_第1张图片

SpringBoot默认扫描启动类所在的包及其子包

Bean注册

注解 说明 位置
@Component 声明bean的基础注解 不属于以下三类时,用此注解
@Controller @Component的衍生注解 标注在控制器类上
@Service @Component的衍生注解 标注在业务类上
@Repository @Component的衍生注解 标注在数据访问类上(由于与mybatis整合,用的少)

如果要注册的bean对象来自于第三方(不是自定义的),是无法用 @Component 及衍生注解声明bean的

  • @Bean

    如果要注册第三方bean,建议在配置类中集中注册

    @Configuration
    public class Config {
    
        @Bean
        public DataSource getDataSource(){
            //如果方法的内部需要使用到ioc容器中已经存在的bean对象,那么只需要在方法上的参数位置声明即可,spring会自动的注入
            return new DruidDataSource();
        }
    }
    
  • @Import

    • 导入 配置类

      @Import(Config.class)
      @SpringBootApplication
      public class HeimaSpringbootBasicsApplication {
          public static void main(String[] args) {
              SpringApplication.run(HeimaSpringbootBasicsApplication.class, args);
          }
      }
      
    • 导入 ImportSelector 接口实现类

      public class LxxImportSelector implements ImportSelector {
          @Override
          public String[] selectImports(AnnotationMetadata importingClassMetadata) {
             return new String[]{"com.alibaba.druid.pool.DruidDataSource"};
          }
      }
      
      @Import(LxxImportSelector.class)
      @SpringBootApplication
      public class HeimaSpringbootBasicsApplication {
          public static void main(String[] args) {
              SpringApplication.run(HeimaSpringbootBasicsApplication.class, args);
          }
      }
      

      ImportSelector接口实现类中selectImports方法的返回值不应该以硬编码的方式写死,这些类名一般是从配置文件中读取的。

      在resources下新建lxx.imports

      com.alibaba.druid.pool.DruidDataSource
      

      修改LxxImportSelector

      public class LxxImportSelector implements ImportSelector {
          @Override
          public String[] selectImports(AnnotationMetadata importingClassMetadata) {
              //读取配置文件的内容
              List<String> imports = new ArrayList<>();
              InputStream is = LxxImportSelector.class.getClassLoader().getResourceAsStream("lxx.imports");
              BufferedReader br = new BufferedReader(new InputStreamReader(is));
              String line = null;
              try {
                  while((line = br.readLine())!=null){
                      imports.add(line);
                  }
              } catch (IOException e) {
                  throw new RuntimeException(e);
              } finally {
                  if (br!=null){
                      try {
                          br.close();
                      } catch (IOException e) {
                          throw new RuntimeException(e);
                      }
                  }
              }
              return imports.toArray(new String[0]);
          }
      }
      

      定义组合注解,优化@Import(LxxImportSelector.class)

      @Target(ElementType.TYPE)
      @Retention(RetentionPolicy.RUNTIME)
      @Import(LxxImportSelector.class)
      public @interface EnableLxxConfig {
      }
      
      @EnableLxxConfig
      @SpringBootApplication
      public class HeimaSpringbootBasicsApplication {
          public static void main(String[] args) {
              SpringApplication.run(HeimaSpringbootBasicsApplication.class, args);
          }
      }
      

注册条件

SpringBoot提供了设置注册生效条件的注解 @Conditional

注解 说明
@ConditionalOnProperty 配置文件中存在对应的属性,才声明该bean
@ConditionalOnBean 当存在当前类型的bean时,才声明该bean
@ConditionalOnMissingBean 当不存在当前类型的bean时,才声明该bean
@ConditionalOnClass 当前环境存在指定的这个类时,才声明该bean
  • @ConditionalOnProperty

    在application.yml中配置

    name: lxx
    

    添加@Conditional

    @Configuration
    public class Config {
    
        @Bean
        //如果配置文件中配置了指定的信息,则注入,否则不注入
        @ConditionalOnProperty(name="name")
        public DataSource getDataSource(){
            return new DruidDataSource();
        }
    }
    

    结果:

    去除application.yml中的name: lxx时:
    HikariDataSource (null)
    
    加上name: lxx时:
    {
    	CreateTime:"2023-12-21 14:00:17",
    	ActiveCount:0,
    	PoolingCount:0,
    	CreateCount:0,
    	DestroyCount:0,
    	CloseCount:0,
    	ConnectCount:0,
    	Connections:[
    	]
    }
    
  • ConditionalOnBean

    @Configuration
    public class Config {
        @Bean
        public Student getStudent() {
            return new Student();
        }
    
        @Bean
        // 如果ioc容器中存在Student则注入
        @ConditionalOnBean(Student.class)
        public DataSource getDataSource() {
            return new DruidDataSource();
        }
    }
    // 结果:注入DataSource
    
  • @ConditionalOnMissingBean

    @Configuration
    public class Config {
        @Bean
        public Student getStudent() {
            return new Student();
        }
    
        @Bean
        // 如果ioc容器中不存在Student则注入
        @ConditionalOnMissingBean(Student.class)
        public DataSource getDataSource() {
            return new DruidDataSource();
        }
    }
    // 结果:没有注入DataSource
    
  • @ConditionalOnClass

    @Configuration
    public class Config {
        @Bean
        //如果当前环境中存在Student类,则注入,否则不注入
        @ConditionalOnClass(Student.class)
        public DataSource getDataSource(){
            return new DruidDataSource();
        }
    }
    
    

你可能感兴趣的:(学习整理-后端,spring,boot,java,后端)