bean的作用域_Spring注解驱动开发之三——@Scope指定作用域、@Lazy懒加载、@Conditional根据条件创建实例...

eedf82280e43235cc7e3b4a9355756cf.png

本文包含以下内容:

  1. 使用@Scope指定作用域测试

  2. 使用@Lazy 配置懒加载测试

  3. 使用@Conditional根据条件创建实例测试

  4. 拓展@Scope、@Lazy、@Conditional

1.使用@Scope指定作用域测试

1)默认情况下,Spring 创建实例的作用域是单例的,通过一下测试得到结论:

@Test  public void test02(){    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);//    String[] definitionNames = applicationContext.getBeanDefinitionNames();//    for (String name : definitionNames) {//      System.out.println(name);//    }//        System.out.println("ioc容器创建完成....");    Object bean = applicationContext.getBean("person");    Object bean2 = applicationContext.getBean("person");    System.out.println(bean == bean2);  }
运行结果,如下图所示:

aff2fec34e59ea10f90c4648099a8b90.png

2)使用 @Scope ()修改 作用域 ,作用域可用参数 prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。每次获取的时候才会调用方法创建对象; singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。以后每次获取就是直接从 容器(map.get())中拿, request:同一次请求创建一个实例 session:同一个session创建一个实例

        将创建实例的方法上添加上@Scope("prototype") 表示多实例的

@Scope("prototype")  @Bean("person")  public Person person01(){    return new Person("张三", 25);  }
  再次运行得到结果如下

d2df794cf047c5377400932beee2029c.png

2.使用@Lazy 配置懒加载测试

在默认的作用域为单例的模式下,可以使用 @Lazy 进行懒加载,即调用的时候,再创建实例对象
  @Lazy  @Bean("person")  public Person person01(){    System.out.println("给容器中添加Person....");    return new Person("张三", 25);  }
配置懒加载前:

403e16b6377462eed304ace0a6256d9a.png

配置懒加载后:

14b1933d3bf2e35ebc74f88b813cf443.png

3.使用@Conditional根据条件创建实例测试

可以通过@Conditional 判断时候满足对应条件再进行创建,即如果要判断当前运行系统来创建指定的Bean 。1)创建 Condition 接口的实现类,作为判断条件的类:
//判断是否windows系统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;  }}
创建判断Linux 系统的实现类,其中两个参数: ConditionContext:判断条件能使用的上下文(环境)如获得获得类加载器、当前环境信息、Bean注册类等信息 AnnotatedTypeMetadata:注释信息
//判断是否linux系统public class LinuxCondition implements Condition {  /**   * ConditionContext:判断条件能使用的上下文(环境)   * AnnotatedTypeMetadata:注释信息   */  @Override  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {    // TODO是否linux系统    //1、能获取到ioc使用的beanfactory    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();    //2、获取类加载器    ClassLoader classLoader = context.getClassLoader();    //3、获取当前环境信息    Environment environment = context.getEnvironment();    //4、获取到bean定义的注册类    BeanDefinitionRegistry registry = context.getRegistry();        String property = environment.getProperty("os.name");        //可以判断容器中的bean注册情况,也可以给容器中注册bean    boolean definition = registry.containsBeanDefinition("person");    if(property.contains("linux")){      return true;    }        return false;  }}
2)建立不同条件对应的Bean 
  @Conditional(WindowsCondition.class)  @Bean("bill")  public Person person01(){    return new Person("Bill Gates",62);  }  @Conditional(LinuxCondition.class)  @Bean("linus")  public Person person02(){    return new Person("linus", 48);  }
3)建立测试方法
@Test  public void test03(){    String[] namesForType = applicationContext.getBeanNamesForType(Person.class);    ConfigurableEnvironment environment = applicationContext.getEnvironment();    //动态获取环境变量的值;Windows 10    String property = environment.getProperty("os.name");    System.out.println(property);    for (String name : namesForType) {      System.out.println(name);    }        Map<String, Person> persons = applicationContext.getBeansOfType(Person.class);    System.out.println(persons);      }
获得结果:

ab53c050eb35c6b7180f04f6daf8120f.png

4)修改启动参数,模拟linux 系统启动 

a7d80784455a48c491bedf6dff13e409.png

添加配置 -Dos.name=linux 

fc83e782b46cb8c079b3dfbc7e418719.png

运行结果:

0c53ce25ff255886a789316a4e8ab3f1.png

5)也可以将注解放在类上,对于所有当前类下所有的@Bean 注解,满足条件才进行创建
//类中组件统一设置。满足当前条件,这个类中配置的所有bean注册才能生效;@Conditional({WindowsCondition.class})public class MainConfig2 {}

4.拓展@Scope、@Lazy、@Conditional

1)@Scope使用场景:几乎 90%以上的业务使用singleton单实例就可以,所以spring默认的类型也是singleton,singleton虽然保证了全局是一个实例,对性能有所提高,但是如果实例中有非静态变量时,会导致线程安全问题,共享资源的竞争当设置为prototype时:每次连接请求,都会生成一个bean实例,也会导致一个问题,当请求数越多, 性能会降低,因为创建的实例,导致GC频繁,gc时长增加2)@Lazy主要作用:@Lazy注解注解的作用主要是减少springIOC容器启动的加载时间当出现循环依赖时,也可以添加@Lazy3)@Conditional 应用场景:在一些需要条件满足才是实例化的类中,使用此注解,我曾经在项目中需要根据不同的场景使用不同的mq中间件的时候使用过,在mq的实例化bean上,加上此注解,根据配置文件的不同,来决定这个bean是否加载至ioc容器中。

-END-

42cd61a1dea98d2726bcb64484987b64.png

可以关注我的公众号,免费获取价值1980元学习资料

点击“在看”,学多少都不会忘~

a382dc9ca9d5ea648c6008648d463ddc.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值