本文包含以下内容:
-
使用@Scope指定作用域测试
-
使用@Lazy 配置懒加载测试
-
使用@Conditional根据条件创建实例测试
-
拓展@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); }
运行结果,如下图所示:
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); }
再次运行得到结果如下
2.使用@Lazy 配置懒加载测试
在默认的作用域为单例的模式下,可以使用
@Lazy 进行懒加载,即调用的时候,再创建实例对象
@Lazy @Bean("person") public Person person01(){ System.out.println("给容器中添加Person...."); return new Person("张三", 25); }
配置懒加载前:
配置懒加载后:
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); }
获得结果:
4)修改启动参数,模拟linux 系统启动
添加配置 -Dos.name=linux
运行结果:
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-
可以关注我的公众号,免费获取价值1980元
学习资料
点击“在看”,学多少都不会忘~