欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 养生 > Spring源码(3)Aware接口、初始化和销毁方法、@Scope、@Primary

Spring源码(3)Aware接口、初始化和销毁方法、@Scope、@Primary

2025/2/24 3:08:38 来源:https://blog.csdn.net/weixin_43823462/article/details/142026543  浏览:    关键词:Spring源码(3)Aware接口、初始化和销毁方法、@Scope、@Primary

1、目标

本文的主要目标是学习Spring源码中Aware接口、初始化和销毁方法、@Scope注解、@Primary注解的使用

2、Aware接口

@Component
public class MyBeanAware implements BeanNameAware, ApplicationContextAware {@Overridepublic void setBeanName(String name) {System.out.println("beanName = " + name);}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {System.out.println("applicationContext = " + applicationContext);}
}

实现BeanNameAware接口,可以重写setBeanName方法
实现ApplicationContextAware接口,可以重写setApplicationContext方法

在这里插入图片描述

3、初始化和销毁方法

初始化方法有3种方式,依次的顺序是@PostConstruct注解指定初始化方法、实现InitializingBean接口并重写afterPropertiesSet方法、@Bean注解上指定initMethod=xxx

销毁方法有3种方式,依次的顺序是@PreDestroy注解指定销毁方法、实现DisposableBean接口并重写destroy方法、@Bean注解上指定destroyMethod=xxx

4、@Scope注解

Scope有单例singleton、多例prototype、request、session、application

单例对象中包含多例对象的属性,多次获取这个属性是是单例的吗还是多例?

结论:还是单例的,因为只会依赖注入1次多例对象

@Component
public class A {@Autowiredprivate B b;public B getB() {return b;}
}

A对象是单例的

@Scope(value = "prototype")
@Component
public class B {
}

B对象设置多例的,即@Scope(value=“prototype”)

@SpringBootApplication
public class Demo02Application {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo02Application.class);A a = applicationContext.getBean("a", A.class);System.out.println(a.getB().getClass());System.out.println(a.getB());System.out.println(a.getB());System.out.println(a.getB());}
}

多个获取A对象中的属性B对象,A对象是单例对象,B对象是多例的,但是B对象只会依赖注入1次,因此多次获取B对象仍然是同一个对象

在这里插入图片描述

多次获取的B对象是同一个对象,说明只会依赖注入1次

如果希望属性是多例对象的话,多次获取可以得到多个不同的对象怎么办?

① @Lazy注解:@Lazy注解会创建属性的CGLIB动态代理对象,因此每次获取这个多例对象的时候动态代理对象会创建一个新的对象

@Component
public class A {@Lazy@Autowiredprivate B b;public B getB() {return b;}
}

A对象是单例对象,依赖注入的B对象是多例对象,因此用@Lazy注解进行懒加载,会创建一个CGLIB动态代理对象,每次获取实际的B对象会创建一个新的B对象

在这里插入图片描述

B对象是CGLIB动态代理对象,每次获取B对象都会创建一个新的B对象

② 在被代理对象上的@Scope注解上添加proxyMode是TARGET_CLASS,表示会使用CGLIB动态代理对象创建一个新的对象

@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
@Component
public class B {
}

被代理对象B对象指定proxyMode=ScopedProxyMode.TARGET_CLASS

在这里插入图片描述

创建了CGLIB动态代理对象,每次获取B对象都会创建一个新的B对象

③ ObjectFactory工厂的getObject方法可以创建多个对象

@Component
public class A {@Autowiredprivate ObjectFactory<B> b;public B getB() {return b.getObject();}
}

依赖注入ObjectFactory工厂对象,通过getObject方法可以创建B对象

在这里插入图片描述

创建CGLIB动态代理对象,多次获取B对象可以得到多个B对象

④ ApplicationContext容器的getBean方法可以获取多例对象的多个对象

@Component
public class A {@Autowiredprivate ApplicationContext applicationContext;public B getB() {return applicationContext.getBean(B.class);}
}

依赖注入容器对象ApplicationContext对象,通过getBean方法多次获取B对象

在这里插入图片描述

创建CGLIB动态代理对象,每次获取B对象可以创建一个新的B对象

5、@Primary注解

@Primary 是 Spring Framework 中的一个注解,用于标记某个 Bean 作为候选 Bean 时的首选项。它的主要作用是在存在多个符合条件的 Bean 时,指定一个 Bean 为首选 Bean

如果只有一个 Bean 实现了接口或类,Spring 会自动选择这个 Bean,而不需要 @Primary

如果没有 @Primary 注解,并且有多个候选 Bean,那么在自动注入时会导致NoUniqueBeanDefinitionException 异常,Spring 会提示有多个 Bean 可用

public interface PaymentService {void processPayment();
}@Component
public class CreditCardPaymentService implements PaymentService {@Overridepublic void processPayment() {// Credit Card payment processing}
}@Component
@Primary
public class PayPalPaymentService implements PaymentService {@Overridepublic void processPayment() {// PayPal payment processing}
}

PaymentProcessor 会自动注入 PayPalPaymentService,因为它被标记为 @Primary

@Service
@RequireArgsConstructor
public class PaymentProcessor {private final PaymentService paymentService;@Autowiredpublic PaymentProcessor(PaymentService paymentService) {this.paymentService = paymentService;}public void process() {paymentService.processPayment();}
}

PaymentProcessor 会自动注入 PayPalPaymentService,因为它被标记为 @Primary

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词