Spring源码从入门到精通---@Profile(十五)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: Spring源码从入门到精通---@Profile(十五)

上篇文章主要说了Aware接口:

如何吧spring底层组件赋值到自定义组件里呢,可以实现xxxAware接口,比如实现ApplicationContextAware接口,可以获取到applicationContext。这些都是由xxxAwareProcessor后置处理器处理的,如ApplicationContextAwareProcessor,先创建bean之后,后置处理器处理吧对应的数据赋值。

Aware&原理---Spring源码从入门到精通(十四)


这篇文章主要说@Profile:

文章分为两个部分,第一部分,数据源环境的搭建。第二部分,@Profile能根据开发环境和测试环境,加在不同的数据源,所以第二部分,如何通过spring提供的@Profile注解,根据我们当前的开发环境,动态的激活和切换一系列组件。


一、数据源环境搭建


先贴一份本文目录

image.png

首先创建myConfigProfile类,创建dataSource.properties配置文件,用我们之前学到过的@PropertySource注解指定加载的配置文件,用三种不同的方法获取到配置文件里面的值,都是我们之前学到过得。


1)、@Value普通获取值

2)、在方法参数上用@Value获取值

3)、实现EmbeddedValueResolverAware接口,解析器获取运行环境里面的值。


配置文件如下:

dataName=root
dataPassword=root
data.driver.class=com.mysql.jdbc.Driver

新的配置类如下:

/**
 * @Profile:根据我们的当前环境,动态的激活和切换一系列组件。
 * 如test环境用test配置,dev环境用dev配置
 *
 * @author keying
 */
@PropertySource(value = {"classpath:/dataSources.properties"})
@Configuration
public class MyConfigProfile implements EmbeddedValueResolverAware {
    @Value("${dataName}")
    private String user;
    private String driverClass;
    @Bean("testDataSource")
    public DataSource test(@Value("${dataPassword}") String password) throws Exception {
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
        comboPooledDataSource.setPassword(password);
        comboPooledDataSource.setUser(user);
        comboPooledDataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/testmac");
        comboPooledDataSource.setDriverClass(driverClass);
        return comboPooledDataSource;
    }
    @Bean("devDataSource")
    public DataSource dev(@Value("${dataPassword}") String password) throws Exception {
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
        comboPooledDataSource.setPassword(password);
        comboPooledDataSource.setUser(user);
        comboPooledDataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/dev");
        comboPooledDataSource.setDriverClass(driverClass);
        return comboPooledDataSource;
    }
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        //配置文件信息放入环境里,解析器从环境信息中获取
        this.driverClass = resolver.resolveStringValue("${data.driver.class}");
    }
}
/**
 * @author keying
 */
public class IOCTestProfile {
    @Test
    public void test() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(
            MyConfigProfile.class);
        //根据类型获取数据源
        String[] strings = applicationContext.getBeanNamesForType(DataSource.class);
        for(String string:strings){
            System.out.println(string);
        }
    }
}

通过junitTest打印可以看到,可以获取我们的两个数据源。本文演示是链接mysql数据库两个不同的database,同学请先在电脑上安装mysql数据库并建立好test和dev两个数据库,不知道安装mysql的自行百度。

image.png

二、@Profile注解使用


1、默认会加载@Profile("default"),指定组件在哪个环境才会注册到容器中,否则都不会注册到IOC容器。


2、改为加载test数据源:

* 1)使用命令行参数,在虚拟机参数位子加:-Dspring.profile.active=test

* 2)使用代码的方式,代码不能用有参构造器加载,从源码可以看到,配置类直接加载,就不能改系统环境里面的值。用无参构造器refresh()容器,其实就是源码里的三步,第一步this()无参创建对象,第二部register注册配置类,第三部刷新创建容器。

* 3)没有配置@Profile的bean,不管在哪个环境都能加载。@Profile可以写在方法上,选择加载指定环境的配置组件。写在配置类上,只有满足当前环境,整个类才会加载。


/**
 * @author keying
 */
public class IOCTestProfile {
    /**
     * 1、默认会加载@Profile("default"),指定组件在哪个环境才会注册到容器中,否则都不会注册到IOC容器。
     * 2、改为加载test数据源:
     * 1)使用命令行参数,在虚拟机参数位子加:-Dspring.profile.active=test
     * 2)使用代码的方式,代码不能用有参构造器加载,从源码可以看到,配置类直接加载,就不能改系统环境里面的值。
     * 用无参构造器refresh()容器,其实就是源码里的三步,第一步this()无参创建对象,第二部register注册配置类,第三部刷新创建容器。
     * 3)没有配置@Profile的bean,不管在哪个环境都能加载。
     *
     * @Profile可以写在方法上,选择加载指定环境的配置组件。写在配置类上,只有满足当前环境,整个类才会加载。
     */
    @Test
    public void test() {
        //第一步创建applicationContext对象
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(
        );
        //第二部设置需要激活的环境
        ConfigurableEnvironment configurableEnvironment = applicationContext.getEnvironment();
        configurableEnvironment.setActiveProfiles("test");
        //第三部注册主配置类
        applicationContext.register(MyConfigProfile.class);
        //第四部刷新启动
        applicationContext.refresh();
        //根据类型获取数据源
        String[] strings = applicationContext.getBeanNamesForType(DataSource.class);
        for (String string : strings) {
            System.out.println(string);
        }
        Yellow yellow = applicationContext.getBean(Yellow.class);
        System.out.println(yellow);
        applicationContext.close();
    }
}
/**
 * @author keying
 * @Profile:根据我们的当前环境,动态的激活和切换一系列组件。如test环境用test配置,dev环境用dev配置
 */
@PropertySource(value = {"classpath:/dataSources.properties"})
@Configuration
//@Profile("test")
public class MyConfigProfile implements EmbeddedValueResolverAware {
    @Value("${dataName}")
    private String user;
    private String driverClass;
    @Bean
    public Yellow yellow(){
        return new Yellow();
    }
    @Profile("test")
    @Bean("testDataSource")
    public DataSource test(@Value("${dataPassword}") String password) throws Exception {
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
        comboPooledDataSource.setPassword(password);
        comboPooledDataSource.setUser(user);
        comboPooledDataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/testmac");
        comboPooledDataSource.setDriverClass(driverClass);
        return comboPooledDataSource;
    }
    @Profile("dev")
    @Bean("devDataSource")
    public DataSource dev(@Value("${dataPassword}") String password) throws Exception {
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
        comboPooledDataSource.setPassword(password);
        comboPooledDataSource.setUser(user);
        comboPooledDataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/dev");
        comboPooledDataSource.setDriverClass(driverClass);
        return comboPooledDataSource;
    }
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        //配置文件信息放入环境里,解析器从环境信息中获取
        this.driverClass = resolver.resolveStringValue("${data.driver.class}");
    }
}

从打印可以看出来,yellow在设置了test环境之后,还是 能打印出来,并且profile注解配置了dev的就打印不出来。

image.png


问:@Confitional注解和@Profile注解都能用在类上,并且都是不满足就不加载,有什么不同?


@Profile是修改系统环境的数据,需要在ioc容器refresh()之前设置,所以不能用有参构造加载配置类。

@Conditional则是在可以获取到环境里面的值,在进行过滤判断,如获取当前运行环境或者系统,进行过滤。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
3月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
131 2
|
3月前
|
数据采集 监控 前端开发
二级公立医院绩效考核系统源码,B/S架构,前后端分别基于Spring Boot和Avue框架
医院绩效管理系统通过与HIS系统的无缝对接,实现数据网络化采集、评价结果透明化管理及奖金分配自动化生成。系统涵盖科室和个人绩效考核、医疗质量考核、数据采集、绩效工资核算、收支核算、工作量统计、单项奖惩等功能,提升绩效评估的全面性、准确性和公正性。技术栈采用B/S架构,前后端分别基于Spring Boot和Avue框架。
158 5
|
2月前
|
存储 安全 Java
Spring Security 入门
Spring Security 是 Spring 框架中的安全模块,提供强大的认证和授权功能,支持防止常见攻击(如 CSRF 和会话固定攻击)。它通过过滤器链拦截请求,核心概念包括认证、授权和自定义过滤器。配置方面,涉及密码加密、用户信息服务、认证提供者及过滤器链设置。示例代码展示了如何配置登录、注销、CSRF防护等。常见问题包括循环重定向、静态资源被拦截和登录失败未返回错误信息,解决方法需确保路径正确和添加错误提示逻辑。
Spring Security 入门
|
1月前
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
|
1月前
|
人工智能 自然语言处理 Java
Spring Cloud Alibaba AI 入门与实践
本文将介绍 Spring Cloud Alibaba AI 的基本概念、主要特性和功能,并演示如何完成一个在线聊天和在线画图的 AI 应用。
346 7
|
2月前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
97 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
2月前
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
74 2
|
2月前
|
Java 数据库连接 数据库
从入门到精通---深入剖析Spring DAO
在Java企业级开发中,Spring框架以其强大的功能和灵活性,成为众多开发者的首选。Spring DAO(Data Access Object)作为Spring框架中处理数据访问的重要模块,对JDBC进行了抽象封装,极大地简化了数据访问异常的处理,并能统一管理JDBC事务。本文将从概述、功能点、背景、业务点、底层原理等多个方面深入剖析Spring DAO,并通过多个Java示例展示其应用实践,同时指出对应实践的优缺点。
34 1
|
3月前
|
监控 Java 数据安全/隐私保护
如何用Spring Boot实现拦截器:从入门到实践
如何用Spring Boot实现拦截器:从入门到实践
83 5
|
3月前
|
前端开发 Java 开发者
Spring生态学习路径与源码深度探讨
【11月更文挑战第13天】Spring框架作为Java企业级开发中的核心框架,其丰富的生态系统和强大的功能吸引了无数开发者的关注。学习Spring生态不仅仅是掌握Spring Framework本身,更需要深入理解其周边组件和工具,以及源码的底层实现逻辑。本文将从Spring生态的学习路径入手,详细探讨如何系统地学习Spring,并深入解析各个重点的底层实现逻辑。
96 9