springBoot注解@Configuration,Profile等

1. @Configuration

  1. 声明这是一个配置类,替换以前配置文件
  2. @Configuration 中所有带 @Bean 注解的方法都会被动态代理,因此调用该方法返回的都是同一个实例
  3. 配置类必须以类的形式提供(不能是工厂方法返回的实例),允许通过生成子类在运行时增强(cglib 动态代理)
  4. 配置类不能是final 类(没法动态代理)
  5. 配置注解通常为了通过 @Bean注解生成 Spring 容器管理的类
  6. 配置类必须是非本地的(即不能在方法中声明,不能是 private)
  7. 任何嵌套配置类都必须声明为static
  8. @Bean方法可能不会反过来创建进一步的配置类(也就是返回的 bean 如果带有 @Configuration,也不会被特殊处理,只会作为普通的 bean)

@Bean 注解方法执行策略

@Configuration
public class MyBeanConfig {

    @Bean
    public Country country(){
        return new Country();
    }

    @Bean
    public UserInfo userInfo(){
        return new UserInfo(country());
    }

}

相信大多数人第一次看到上面userInfo() 中调用country()时,会认为这里的 Country和上面@Bean方法返回的 Country 可能不是同一个对象,因此可能会通过下面的方式来替代这种方式:

@Autowired

private Country country;

实际上不需要这么做,直接调用country()方法返回的是同一个实例

2. @ComponentScan 包扫描

如果是java8 可以使用可重复注解,以前可以使用ComponentScans、

2.1. 过滤规则

  1. FilterType.ANNOTATION:按照注解
  2. FilterType.ASSIGNABLE_TYPE:按照给定的类型
  3. FilterType.ASPECTJ:使用ASPECTJ表达式
  4. FilterType.REGEX:使用正则指定
  5. FilterType.CUSTOM:使用自定义规则

2.2. 包含/不包含扫描

@Configuration
@ComponentScan(value = "com.du",excludeFilters = {
	@ComponentScan.Filter(type = FilterType.ANNOTATION,
                        classes = { Service.class, Controller.class})})
@ComponentScan(includeFilters = {
	@ComponentScan.Filter(type = FilterType.ANNOTATION,
                        classes = {Controller.class })},
              					 useDefaultFilters = false  )
public class ComponentScanTest {
}

2.3. 指定规则过滤

@Configuration
@ComponentScan(includeFilters = {
    @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}),
    @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {Account.class})
}, useDefaultFilters = false)

2.4. 自定义规则

public class MyTypeFilter implements TypeFilter {
  /**
     * @param metadataReader 读取到的当前正在扫描的类的信息
     * @param metadataReaderFactory 可以获取到其他任何类信息的
     */
  @Override
  public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
    //获取当前类注解的信息
    AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
    //获取当前正在扫描的类的类信息
    ClassMetadata classMetadata = metadataReader.getClassMetadata();
    //获取当前类资源(类的路径)
    Resource resource = metadataReader.getResource();
    String className = classMetadata.getClassName();
    System.out.println("--->"+className);
    if(className.contains("er")){
      return true;
    }
    return false;
  }
}
@Configuration
@ComponentScans(
value = {@ComponentScan(value="com.du",includeFilters = {
            @Filter(type=FilterType.CUSTOM,classes={MyTypeFilter.class})
            },useDefaultFilters = false)})

3. @Profile

基于多环境激活

使用命令行动态参数: 在虚拟机参数位置加载 -Dspring.profiles.active=test

@Configuration
public class ProfileShow  implements EmbeddedValueResolverAware {
  private StringValueResolver valueResolver;
  private String  driverClass;

  @Profile("dev")
  @Bean(name = "ds1")
  public DataSource createDataSource1() {
    DruidDataSource ds = new DruidDataSource();
    ds.setDriverClassName(driverClass);
    ds.setUrl("jdbc:mysql://120.48.14.129:3306/study");
    ds.setUsername("root");
    ds.setPassword("root");
    return ds;
  }

  @Profile("prod")
  @Bean(name = "ds2")
  public DataSource createDataSource2() {
    DruidDataSource ds = new DruidDataSource();
    ds.setDriverClassName(driverClass);
    ds.setUrl("jdbc:mysql://120.48.14.129:3306/study");
    ds.setUsername("root");
    ds.setPassword("root");
    return ds;
  }

  @Override
  public void setEmbeddedValueResolver(StringValueResolver resolver) {
    this.valueResolver = resolver;
    driverClass = valueResolver.resolveStringValue("${jdbc.driver}");
  }

  @Test
  public void  test(){
    AnnotationConfigApplicationContext applicationContext =
    new AnnotationConfigApplicationContext();
    //1、创建一个applicationContext
    //2、设置需要激活的环境
    applicationContext.getEnvironment().setActiveProfiles("dev");
    //3、注册主配置类
    applicationContext.register(ProfileShow.class);
    //4、启动刷新容器
    applicationContext.refresh();
    String[] beanNamesForType = applicationContext.getBeanNamesForType(DataSource.class);
    System.out.println(beanNamesForType);
  }

4. @Lookup

  1. 单例组件依赖非单例组件,非单例组件获取需要使用方法
  2. Autowired 获取的都是单的,包括对象里面包含对象
  3. 用于Get 方法上 目的 获取的对象的对象是多实例的
  4. @Bean 注解对象无效
@Component
public class Person {

   public Person(){
     System.out.println("person创建....");
   }

   private String name;
   private Cat cat;
   
   public void setName(String name) {
     this.name = name;
   }
   public String getName() {
     return name;
   }
  public void setCat(Cat cat) {
     this.cat = cat;
   }

 @Lookup
   public Cat getCat() {
     return cat;
   }
}
 
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Component
public class Cat {

   private String name;

   public void setName(String name) {
     this.name = name;
   }

   public String getName() {
     return name;
   }
}
 
 
@ComponentScan("com.du.anno.Lookup")
@Configuration
public class MainConfig {

}

public class AnnotationMainTest {

   public static void main(String[] args) {

     ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);

     Cat bean1 = applicationContext.getBean(Cat.class);

     Cat bean2 = applicationContext.getBean(Cat.class);

     //false
     System.out.println(bean1 == bean2);

     Person bean = applicationContext.getBean(Person.class);
     Person bean3 = applicationContext.getBean(Person.class);

     Cat cat = bean.getCat();
     Cat cat1 = bean3.getCat();
     //true
     System.out.println(cat1 == cat);
     
   }
}

5. @Scope

  1. 声明组件的作用范围
  2. SCOPE_PROTOTYPE
  3. SCOPE_SINGLETON

6. @Order

数字越小优先级越高,越先工作

7. @Primary

同类组件如果有多个,标注主组件

8. @Lazy

懒加载:容器启动不创建对象。

第一次使用(获取)Bean创建对象,并初始化

@Lazy
@Bean("person")
public Person person(){
  System.out.println("给容器中添加Person....");
  return new Person("张三", 25);
}

9. @DependsOn

组件之间声明依赖关系

10. @Indexed

加速注解,所有标注了 @Indexed 的组件,直接会启动快速加载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值