目录
1、@Lazy 懒加载bean
@Lazy用于指定单例bean实例化的时机,在没有指定此注解时,单例bean会在容器初始化时就被创建。而当使用此注解后,单例对象的创建时机会在该bean在被第一次使用时创建,并且只创建一次。第二次及以后获取使用就不再创建。
在实际开发场景中,并不是所有bean都要一开始就被创建的,有些可以等到使用时才创建。此时就可以使用该注解实现。此注解只对单例bean有用,原型bean时此注解不起作用。
原型bean是在每次请求时都会创建一个新的实例,而不像单例bean那样只有一个实例。因此,使用
@Lazy
注解对原型bean没有实际意义,因为即使不使用该注解,每次请求都会创建一个新的实例。所以,@Lazy
注解只对那些在容器初始化时就被创建的单例bean有用。@Lazy注解可以作用在类上、方法上、构造器上、方法参数上、成员变量中。
@Lazy注解作用于类上时,通常与@Component及其衍生注解配合使用。
@Lazy注解作用于方法上时,通常与@Bean注解配合使用。
示例:
没有使用@Lazy注解时
@Component //把E配置成bean
public class E {
public E(){
//当调用这个无参构造函数创造bean时,就会执行这条打印语句
System.out.println("E");
}
}
//测试类
@SpringBootTest(classes = TestLazy.class)
@ComponentScan("com.lt.lazyDemo")//我的E类是在"com.lt.lazyDemo"这个包下,所以我这里填这个路径,你们改成自己的E类的路径
public class TestLazy {
@Test
public void test(){
}
}
1.1、与@component配合使用
@Component
@Lazy
public class E {
public E(){
//当调用这个无参构造函数创造bean时,就会执行这条打印语句
System.out.println("E");
}
}
//测试类的代码不变
1.2、与@Bean注解配合使用
//把E类上面的注解都注释掉
//测试类
@SpringBootTest(classes = TestLazy.class)
//使用@Bean的方式配置bean时,@ComponentScan注解就可用可不用了
//@ComponentScan("com.lt.lazyDemo")
public class TestLazy {
@Bean
@Lazy
public E e1(){
return new E();
}
@Test
public void test(){
}
}
使用@Lazy注解的好处:在spring中,默认的bean会在启动的时候就会创建,如果说某些Bean非常大,如果在启动的时候就创建就会影响启动速度,就可以把那些大的Bean设置成懒加载,这样可以优化启动速度
2、@Scope bean的作用域
@Scope注解是 Spring IOC 容器中的一个作用域,在 Spring IOC 容器中,他用来配置Bean实例的作用域对象。@Scope 具有以下几种作用域:
singleton 单实例的(单例)(默认) | ----全局有且仅有一个实例 |
prototype 多实例的(多例) | ---- 每次获取Bean的时候会有一个新的实例 |
reqeust 同一次请求 | ----request:每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效 |
session 同一个会话级别 | ---- session:每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效 |
这里只需要掌握singleton和prototype这两种就行了,其他两种感兴趣的可以自己去了解了解
@Scope注解作用于类上时,通常与@Component及其衍生注解配合使用。
@Component
@Scope(value = "prototype")
public class F {
public F(){
System.out.println("F");
}
}
@Scope注解作用于方法上时,通常与@Bean注解配合使用。
@Bean
@Scope(value = "prototype")
public F f(){
return new F();
}
@Scope注解使用示例:
2.1、不指定@Scope
在不指定@Scope的情况下,所有的bean都是单实例的bean,而且是饿汉模式加载(容器启动实例就创建好了)
public class F {
public F(){
System.out.println("F");
}
}
//测试类TestScope
@SpringBootTest(classes = TestScope.class)
public class TestScope {
@Bean
public F f(){
return new F();
}
@Test
public void test(@Autowired F f, @Autowired F ff, @Autowired F fff){
System.out.println(f);
System.out.println(ff);
System.out.println(fff);
}
}
2.2、指定@Scope为 prototype
指定@Scope为 prototype 表示为多实例的,是懒汉模式加载(IOC容器启动的时候,并不会创建对象,而是 在第一次使用的时候才会创建)
//F类的代码没有变
//测试类TestScope
@SpringBootTest(classes = TestScope.class)
public class TestScope {
@Bean
// 默认单例@Scope("singleton")
// @Scope("prototype")多例
@Scope(value = "prototype")
public F f(){
return new F();
}
@Test
public void test(@Autowired F f, @Autowired F ff, @Autowired F fff){
System.out.println(f);
System.out.println(ff);
System.out.println(fff);
}
}
多例模式会比单例模式对内存造成更大的一个使用,内存开销会比较大。但是有时候不得不使用多例模式,因为单例模式在有些情况下可能会造成线程不安全
3、@Conditional 条件注解
@Conditional注解:可以用在任何类型或者方法上面,通过@Conditional注解可以配置一些条件判断,当所有条件都满足的时候,被@Conditional标注的目标才会被spring容器处理。
比如可以通过@Conditional来控制bean是否需要注册,控制被@Configuration标注的配置类是需要需要被解析等
@Conditional 注解上有一个 value 属性,其值只能为 Condition 类型的数组,使用 @Conditional 时必须进行指定。Condition 是指具体的条件,条件是否匹配由 Condition 进行控制,其是一个接口,需要我们自己实现。
@Conditional使用的3步骤
(1)自定义一个类,实现Condition或ConfigurationCondition接口,实现matches方法
(2)在目标对象上使用@Conditional注解,并指定value的值为自定义的Condition类型
(3)启动spring容器加载资源,此时@Conditional就会起作用了
示例:
//自定义类ConditionalService
public class ConditionalService {
public ConditionalService(){
System.out.println("ConditionalService");
}
}
//Condition接口的实现类MyCondition
public class MyCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return true; //返回true为bean生效,false为bean不生效
}
}
@SpringBootTest(classes = TestConditional.class)
public class TestConditional {
@Bean
//必须指定一个实现了Condition接口的类,由matches方法的返回值决定当前Bean是否生效
@Conditional(MyCondition.class)
public ConditionalService conditionalService(){
return new ConditionalService();
}
@Test
public void test(@Autowired(required = false) ConditionalService conditionalService){
System.out.println(conditionalService);
}
}
推荐:
【Spring】IOC/DI中常用的注解@Order与@DependsOn-CSDN博客https://blog.csdn.net/m0_65277261/article/details/138167160?spm=1001.2014.3001.5501【Spring】依赖注入(DI)时常用的注解@Autowired和@Value_配置类 使用@autowired 类型注入-CSDN博客https://blog.csdn.net/m0_65277261/article/details/137784706?spm=1001.2014.3001.5501【Java网络编程】TCP通信(Socket 与 ServerSocket)和UDP通信的三种数据传输方式_socket tcpserver-CSDN博客https://blog.csdn.net/m0_65277261/article/details/137926277?spm=1001.2014.3001.5501