后端开发速查:必备的Spring IOC 容器底层注解使用【完整版】(下)

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: 后端开发速查:必备的Spring IOC 容器底层注解使用【完整版】(下)

六、Bean的初始化方法和销毁方法.

  • ①:什么是bean的生命周期?

bean的创建----->初始化----->销毁方法

由容器管理Bean的生命周期,我们可以通过自己指定bean的初始化方法和bean的销毁方法

@Configuration
public class MainConfig {
//指定了bean的生命周期的初始化方法和销毁方法.
@Bean(initMethod = "init",destroyMethod = "destroy")
public Car car() {
return new Car();
}
}

针对单实例bean的话,容器启动的时候,bean的对象就创建了,而且容器销毁的时候,也会调用Bean的销毁方法针对多实例bean的话,容器启动的时候,bean是不会被创建的而是在获取bean的时候被创建,而且bean的销毁不受IOC容器的管理.


②:通过 InitializingBean和DisposableBean 的二个接口实现bean的初始化以及销毁方法

@Component
public class Person implements InitializingBean,DisposableBean {
public Person() {
System.out.println("Person的构造方法");
}
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean的destroy()方法 ");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean的 afterPropertiesSet方法");
}
}
  • ③:通过JSR250规范 提供的注解@PostConstruct 和@ProDestory标注的方法
@Component
public class Book {
public Book() {
System.out.println("book 的构造方法");
}
@PostConstruct
public void init() {
System.out.println("book 的PostConstruct标志的方法");
}
@PreDestroy
public void destory() {
System.out.println("book 的PreDestory标注的方法");
}
}


④:通过Spring的BeanPostProcessor的 bean的后置处理器会拦截所有bean创建过程

postProcessBeforeInitialization 在init方法之前调用

**postProcessAfterInitialization 在init方法之后调用

@Component
public class TaoRenBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("TaoRenBeanPostProcessor...postProcessBeforeInitialization:"+beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("TaoRenBeanPostProcessor...postProcessAfterInitialization:"+beanName);
return bean;
}
}


BeanPostProcessor的执行时机

populateBean(beanName, mbd, instanceWrapper)
initializeBean{
applyBeanPostProcessorsBeforeInitialization()
invokeInitMethods{
isInitializingBean.afterPropertiesSet
自定义的init方法
}
applyBeanPostProcessorsAfterInitialization()方法
}


七、通过@Value +@PropertySource来给组件赋值

public class Person {
//通过普通的方式
@Value("司马")
private String firstName;
//spel方式来赋值
@Value("#{28-8}")
private Integer age;
通过读取外部配置文件的值
@Value("${person.lastName}")
private String lastName;
}
@Configuration
@PropertySource(value = {"classpath:person.properties"}) //指定外部文件的位置
public class MainConfig {
@Bean
public Person person() {
return new Person();
}
}


八、自动装配 @AutoWired的使用

自动注入:

//一个Dao
@Repository
public class TaoRenDao {
}
@Service
public class TaoRenService {
@Autowired
private TaoRenDao TaoRenDao;


结论:

a:自动装配首先时按照类型进行装配,若在IOC容器中发现了多个相同类型的组件,那么就按照 属性名称来进行装配

@Autowired

private TaoRenDao TaoRenDao;

比如,我容器中有二个TaoRenDao类型的组件 一个叫TaoRenDao 一个叫TaoRenDao2

那么我们通过@AutoWired 来修饰的属性名称时TaoRenDao,那么拿就加载容器的TaoRenDao组件,若属性名称为

tulignDao2 那么他就加载的时TaoRenDao2组件

b:假设我们需要指定特定的组件来进行装配,我们可以通过使用@Qualifier(“TaoRenDao”)来指定装配的组件

或者在配置类上的@Bean加上@Primary注解

@Autowired
@Qualifier("TaoRenDao")
private TaoRenDao TaoRenDao2;


c:假设我们容器中即没有TaoRenDao 和TaoRenDao2,那么在装配的时候就会抛出异常

No qualifying bean of type ‘com.TaoRen.testautowired.TaoRenDao’ available

若我们想不抛异常 ,我们需要指定 required为false的时候可以了

@Autowired(required = false)
@Qualifier("TaoRenDao")
private TaoRenDao TaoRenDao2;
  • d:@Resource(JSR250规范)
    功能和@AutoWired的功能差不多一样,但是不支持@Primary 和@Qualifier的支持
  • e:@InJect(JSR330规范)
    需要导入jar包依赖功能和支持@Primary功能 ,但是没有Require=false的功能
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>

f:使用autowired 可以标注在方法上标注在set方法上

//@Autowired
public void setTaoRenLog(TaoRenLog TaoRenLog) {
this.TaoRenLog = TaoRenLog;
}


标注在构造方法上

@Autowired
public TaoRenAspect(TaoRenLog TaoRenLog) {
this.TaoRenLog = TaoRenLog;
}


标注在配置类上的入参中(可以不写)

@Bean
public TaoRenAspect TaoRenAspect(@Autowired TaoRenLog TaoRenLog) {
TaoRenAspect TaoRenAspect = new TaoRenAspect(TaoRenLog);
return TaoRenAspect;
}


九、自定义组件

我们自己的组件时,需要使用spring ioc的底层组件的时候,比如 ApplicationContext等.我们可以通过实现XXXAware接口来实现

@Component
public class TaoRenCompent implements ApplicationContextAware,BeanNameAware {
private ApplicationContext applicationContext;
@Override
public void setBeanName(String name) {
System.out.println("current bean name is :【"+name+"】");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}


十、@Profile注解指定环境

过@Profile注解来根据环境来激活标识不同的Bean@Profile标识在类上,那么只有当前环境匹配,整个配置类才会生效@Profile标识在Bean上 ,那么只有当前环境的Bean才会被激活没有标志为@Profile的bean 不管在什么环境都可以被激活.

@Configuration
@PropertySource(value = {"classpath:ds.properties"})
public class MainConfig implements EmbeddedValueResolverAware {
@Value("${ds.username}")
private String userName;
@Value("${ds.password}")
private String password;
private String jdbcUrl;
private String classDriver;
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
this.jdbcUrl = resolver.resolveStringValue("${ds.jdbcUrl}");
this.classDriver = resolver.resolveStringValue("${ds.classDriver}");
}
//标识为测试环境才会被装配
@Bean
@Profile(value = "test")
public DataSource testDs() {
return buliderDataSource(new DruidDataSource());
}
//标识开发环境才会被激活
@Bean
@Profile(value = "dev")
public DataSource devDs() {
return buliderDataSource(new DruidDataSource());
}
//标识生产环境才会被激活
@Bean
@Profile(value = "prod")
public DataSource prodDs() {
return buliderDataSource(new DruidDataSource());
}
private DataSource buliderDataSource(DruidDataSource dataSource) {
dataSource.setUsername(userName);
dataSource.setPassword(password);
dataSource.setDriverClassName(classDriver);
dataSource.setUrl(jdbcUrl);
return dataSource;
}
}


激活切换环境的方法

  • 方法一:通过运行时jvm参数来切换 -Dspring.profiles.active=test|dev|prod
  • 方法二:通过代码的方式来激活
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setActiveProfiles("test","dev");
ctx.register(MainConfig.class);
ctx.refresh();
printBeanName(ctx);
}


相关文章
|
28天前
|
XML Java 数据格式
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
Spring 第二节内容补充 关于Bean配置的更多内容和细节 万字详解!
144 18
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
|
16天前
|
XML Java 测试技术
spring复习01,IOC的思想和第一个spring程序helloWorld
Spring框架中IOC(控制反转)的思想和实现,通过一个简单的例子展示了如何通过IOC容器管理对象依赖,从而提高代码的灵活性和可维护性。
spring复习01,IOC的思想和第一个spring程序helloWorld
|
4天前
|
存储 开发框架 Java
什么是Spring?什么是IOC?什么是DI?IOC和DI的关系? —— 零基础可无压力学习,带源码
文章详细介绍了Spring、IOC、DI的概念和关系,解释了控制反转(IOC)和依赖注入(DI)的原理,并提供了IOC的代码示例,阐述了Spring框架作为IOC容器的应用。
7 0
什么是Spring?什么是IOC?什么是DI?IOC和DI的关系? —— 零基础可无压力学习,带源码
|
18天前
|
人工智能 开发框架 Java
重磅发布!AI 驱动的 Java 开发框架:Spring AI Alibaba
随着生成式 AI 的快速发展,基于 AI 开发框架构建 AI 应用的诉求迅速增长,涌现出了包括 LangChain、LlamaIndex 等开发框架,但大部分框架只提供了 Python 语言的实现。但这些开发框架对于国内习惯了 Spring 开发范式的 Java 开发者而言,并非十分友好和丝滑。因此,我们基于 Spring AI 发布并快速演进 Spring AI Alibaba,通过提供一种方便的 API 抽象,帮助 Java 开发者简化 AI 应用的开发。同时,提供了完整的开源配套,包括可观测、网关、消息队列、配置中心等。
775 8
|
13天前
|
缓存 Java Spring
手写Spring Ioc 循环依赖底层源码剖析
在Spring框架中,IoC(控制反转)是一个核心特性,它通过依赖注入(DI)实现了对象间的解耦。然而,在实际开发中,循环依赖是一个常见的问题。
26 4
|
16天前
|
XML Java 开发者
经典面试---spring IOC容器的核心实现原理
作为一名拥有十年研发经验的工程师,对Spring框架尤其是其IOC(Inversion of Control,控制反转)容器的核心实现原理有着深入的理解。
57 3
|
29天前
|
Java 数据库连接 数据格式
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
IOC/DI配置管理DruidDataSource和properties、核心容器的创建、获取bean的方式、spring注解开发、注解开发管理第三方bean、Spring整合Mybatis和Junit
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
|
21天前
|
Linux iOS开发 Docker
Docker:容器化技术的领航者 —— 从基础到实践的全面解析
在云计算与微服务架构日益盛行的今天,Docker作为容器化技术的佼佼者,正引领着一场软件开发与部署的革命。它不仅极大地提升了应用部署的灵活性与效率,还为持续集成/持续部署(CI/CD)提供了强有力的支撑。
203 69
|
2天前
|
存储 监控 Shell
docker的底层原理二:容器运行时环境
本文深入探讨了Docker容器运行时环境的关键技术,包括命名空间、控制组、联合文件系统、容器运行时以及分离的进程树,这些技术共同确保了容器的隔离性、资源控制和可移植性。
13 5
|
9天前
|
Kubernetes Cloud Native 持续交付
云原生之旅:Docker容器化与Kubernetes集群管理
【9月更文挑战第33天】在数字化转型的浪潮中,云原生技术如同一艘航船,带领企业乘风破浪。本篇文章将作为你的航海指南,从Docker容器化的基础讲起,直至Kubernetes集群的高级管理,我们将一起探索云原生的奥秘。你将学习到如何封装应用、实现环境隔离,以及如何在Kubernetes集群中部署、监控和扩展你的服务。让我们启航,驶向灵活、可伸缩的云原生未来。