• 【Spring篇】IOC/DI配置管理第三方bean


    一、案例:数据源对象管理

    在这一节中,我们将通过一个案例来学习下对于第三方bean该如何进行配置管理。 以后我们会用到很多第三方的bean,本次案例将使用咱们前面提到过的数据源Druid(德鲁伊)C3P0来配置学习下。

    1.环境准备

    • 创建一个Maven项目

    • pom.xml添加依赖
    1. "1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    5. <modelVersion>4.0.0modelVersion>
    6. <groupId>com.itheimagroupId>
    7. <artifactId>spring_09_datasourceartifactId>
    8. <version>1.0-SNAPSHOTversion>
    9. <dependencies>
    10. <dependency>
    11. <groupId>org.springframeworkgroupId>
    12. <artifactId>spring-contextartifactId>
    13. <version>5.2.10.RELEASEversion>
    14. dependency>
    15. <dependency>
    16. <groupId>com.alibabagroupId>
    17. <artifactId>druidartifactId>
    18. <version>1.1.16version>
    19. dependency>
    20. <dependency>
    21. <groupId>c3p0groupId>
    22. <artifactId>c3p0artifactId>
    23. <version>0.9.1.2version>
    24. dependency>
    25. <dependency>
    26. <groupId>mysqlgroupId>
    27. <artifactId>mysql-connector-javaartifactId>
    28. <version>5.1.47version>
    29. dependency>
    30. dependencies>
    31. project>
    •  resources下添加spring的配置文件applicationContext.xml
    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="
    5. http://www.springframework.org/schema/beans
    6. http://www.springframework.org/schema/beans/spring-beans.xsd">
    7. beans>
    • 编写一个运行类App
    1. public class App {
    2. public static void main(String[] args) {
    3. ApplicationContext ctx = new
    4. ClassPathXmlApplicationContext("applicationContext.xml");
    5. }
    6. }

    2.实现Druid管理

    思路分析

    需求 : 使用 Spring IOC 容器来管理 Druid 连接池对象
    1. 使用第三方的技术,需要在 pom.xml 添加依赖【前面已导入】
    2. 在配置文件中将【第三方的类】制作成一个 bean ,让 IOC 容器进行管理
    3. 数据库连接需要基础的四要素 驱动 连接 用户名 密码 ,【如何注入】到对应的 bean
    4. IOC 容器中获取对应的 bean 对象,将其打印到控制台查看结果

    步骤1:配置第三方bean

    applicationContext.xml配置文件中添加DruidDataSource的配置

    1. <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    2. <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    3. <property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>
    4. <property name="username" value="root"/>
    5. <property name="password" value="root"/>
    6. bean>
    说明 :
    driverClassName: 数据库驱动
    url: 数据库连接地址
    username: 数据库连接用户名
    password: 数据库连接密码
    数据库连接的四要素要和自己使用的数据库信息一致。
    步骤2 : IOC 容器中获取对应的 bean 对象
    1. public class App {
    2. public static void main(String[] args) {
    3. ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    4. DataSource dataSource = (DataSource) ctx.getBean("dataSource");
    5. System.out.println(dataSource);
    6. }
    7. }

    做完案例后,我们可以将刚才思考的两个问题答案说下 :
    • 第三方的类指的是什么?
    DruidDataSource
    • 如何注入数据库连接四要素?
    setter注入

    3.实现C3P0管理

    完成了 DruidDataSource 的管理,接下来我们再来加深下练习,这次我们来管理 C3P0 数据源,具体的实现步骤是什么呢?
    步骤1 : 配置第三方 bean
    applicationContext.xml 配置文件中添加配置
    1. <bean class="com.mchange.v2.c3p0.ComboPooledDataSource">
    2. <property name="driverClass" value="com.mysql.jdbc.Driver"/>
    3. <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring_db"/>
    4. <property name="user" value="root"/>
    5. <property name="password" value="root"/>
    6. <property name="maxPoolSize" value="1000"/>
    7. bean>
    注意 :
    • ComboPooledDataSource的属性是通过setter方式进行注入
    • 想注入属性就需要在ComboPooledDataSource类或其上层类中有提供属性对应的setter方法
    • C3P0的四个属性和Druid的四个属性是不一样的

    运行程序

    二、加载properties文件

    上节中我们已经完成两个数据源 druid C3P0 的配置,但是其中包含了一些问题,我们来分析下 :
    • 这两个数据源中都使用到了一些固定的常量如数据库连接四要素,把这些值写在Spring的配置文件中不利于后期维护
    • 需要将这些值提取到一个外部的properties配置文件中
    • Spring框架如何从配置文件中读取属性值来配置就是接下来要解决的问题。

    1.第三方bean属性优化

    实现思路

    需求 : 将数据库连接四要素提取到 properties 配置文件, spring 来加载配置信息并使用这些信息
    来完成属性注入。
    1. resources 下创建一个 jdbc.properties( 文件的名称可以任意 )
    5 2. 将数据库连接四要素配置到配置文件中
    3. Spring 的配置文件中加载 properties 文件
    4. 使用加载到的值实现属性注入
    其中第 3 4 步骤是需要大家重点关注,具体是如何实现。

    实现步骤  

    步骤 1: 准备 properties 配置文件
    resources 下创建一个 jdbc.properties 文件 , 并添加对应的属性键值对
    1. jdbc.driver=com.mysql.jdbc.Driver
    2. jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db
    3. jdbc.username=root
    4. jdbc.password=root
    步骤 2: 开启 context 命名空间
    applicationContext.xml 中开 context 命名空间
    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xmlns:context="http://www.springframework.org/schema/context"
    5. xsi:schemaLocation="
    6. http://www.springframework.org/schema/beans
    7. http://www.springframework.org/schema/beans/spring-beans.xsd
    8. http://www.springframework.org/schema/context
    9. http://www.springframework.org/schema/context/spring-context.xsd
    步骤 3: 加载 properties 配置文件
    在配置文件中使用 context 命名空间下的标签来加载 properties 配置文件
    <context:property-placeholder location="jdbc.properties"/>
    步骤 4: 完成属性注入
    使用 ${key} 来读取 properties 配置文件中的内容并完成属性注入
    1. <context:property-placeholder location="jdbc.properties"/>
    2. <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    3. <property name="driverClassName" value="${jdbc.driver}"/>
    4. <property name="url" value="${jdbc.url}"/>
    5. <property name="username" value="${jdbc.username}"/>
    6. <property name="password" value="${jdbc.password}"/>
    7. bean>
    至此,读取外部 properties 配置文件中的内容就已经完成。

    2.读取单个属性

    实现思路

    对于上面的案例,效果不是很明显,我们可以换个案例来演示下:

    需求 : properties 配置文件中读取 key name 的值,并将其注入到 BookDao 中并在 save 方法中进行打印。
    1. 在项目中添加 BookDao BookDaoImpl
    2. BookDaoImpl 添加一个 name 属性并提供 setter 方法
    3. jdbc.properties 中添加数据注入到 bookDao 中打印方便查询结果
    4. applicationContext.xml 添加配置完成配置文件加载、属性注入 (${key})

     实现步骤

    步骤 1: 在项目中添对应的类
    BookDao BookDaoImpl 类,并在 BookDaoImpl 类中添加 name 属性与 setter 方法
    1. public interface BookDao {
    2. public void save();
    3. }
    1. public class BookDaoImpl implements BookDao {
    2. private String name;
    3. public void setName(String name) {
    4. this.name = name;
    5. }
    6. public void save() {
    7. System.out.println("book dao save ..." + name);
    8. }
    9. }
    步骤 2: 完成配置文件的读取与注入
    applicationContext.xml 添加配置, bean 的配置管理 读取外部 properties 依赖注入 :
    1. <context:property-placeholder location="jdbc.properties"/>
    2. <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
    3. <property name="name" value="${jdbc.driver}"/>
    4. bean>
    步骤 3: 运行程序
    App 类中,从 IOC 容器中获取 bookDao 对象,调用方法,查看值是否已经被获取到并打印控制台
    1. public class App {
    2. public static void main(String[] args) {
    3. ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    4. BookDao bookDao = (BookDao) ctx.getBean("bookDao");
    5. bookDao.save();
    6. }
    7. }

    3.注意事项  

    至此,读取 properties 配置文件中的内容就已经完成,但是在使用的时候,有些注意事项 :

    问题一:键值对的keyusername引发的问题

    1.properties中配置键值对的时候,如果key设置为username

    username=root666
    2. applicationContext.xml 注入该属性
    1. <context:property-placeholder location="jdbc.properties"/>
    2. <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
    3. <property name="name" value="${username}"/>
    4. bean>
    3. 运行后,在控制台打印的却不是 root666 ,而是自己电脑的用户名

    4. 出现问题的原因是 - placeholder/> 标签会加载系统的环境变量,而且环境
    变量的值会被优先加载,如何查看系统的环境变量 ?
    1. public class AppSystemProperties {
    2. public static void main(String[] args) {
    3. Map env = System.getenv();
    4. System.out.println(env);
    5. }
    6. }
    大家可以自行运行,在打印出来的结果中会有一个 USERNAME=XXX[ 自己电脑的用户名称 ]
    5. 解决方案
        <context:property-placeholder location="jdbc.properties" system-properties-mode="NEVER"/>
    system-properties-mode: 设置为 NEVER, 表示不加载系统属性,就可以解决上述问题。
    当然还有一个解决方案就是避免使用 username 作为属性的 key
    问题二:当有多个properties配置文件需要被加载,该如何配置?
    1. 调整下配置文件的内容,在 resources 下添加 jdbc.properties , jdbc2.properties , 内容如
    :
    jdbc.properties
    1. jdbc.driver=com.mysql.jdbc.Driver
    2. jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db
    3. jdbc.username=root
    4. jdbc.password=root
    jdbc2.properties
    username=root666
    2. 修改 applicationContext.xml
    1. <context:property-placeholder
    2. location="jdbc.properties,jdbc2.properties" system-properties-mode="NEVER"/>
    3. <context:property-placeholder location="*.properties" system-properties-mode="NEVER"/>
    4. <context:property-placeholder location="classpath:*.properties"
    5. system-properties-mode="NEVER"/>
    6. <context:property-placeholder location="classpath*:*.properties"
    7. system-properties-mode="NEVER"/>
    说明 :
    • 方式一:可以实现,如果配置文件多的话,每个都需要配置
    • 方式二: *.properties代表所有以properties结尾的文件都会被加载,可以解决方式一的问题,但是不标准
    • 方式三:标准的写法,classpath:代表的是从根路径下开始查找,但是只能查询当前项目的根路径
    • 方式四:不仅可以加载当前项目还可以加载当前项目所依赖的所有项目的根路径下的properties配置文件

    三、核心容器

    前面已经完成bean与依赖注入的相关知识学习,接下来我们主要学习的是IOC容器中的核心容器

    这里所说的核心容器,大家可以把它简单的理解为ApplicationContext,前面虽然已经用到过,但

    是并没有系统的学习,接下来咱们从以下几个问题入手来学习下容器的相关知识:

    • 如何创建容器?
    • 创建好容器后,如何从容器中获取bean对象?
    • 容器类的层次结构是什么?
    • BeanFactory是什么?

    1.环境准备

    在学习和解决上述问题之前,先来准备下案例环境:

    • 创建一个Maven项目
    • pom.xml添加Spring的依赖
    1. <dependencies>
    2. <dependency>
    3. <groupId>org.springframeworkgroupId>
    4. <artifactId>spring-contextartifactId>
    5. <version>5.2.10.RELEASEversion>
    6. dependency>
    7. dependencies>
    • resources下添加applicationContext.xml
    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="
    5. http://www.springframework.org/schema/beans
    6. http://www.springframework.org/schema/beans/spring-beans.xsd">
    7. <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
    8. beans>
    • 添加BookDao和BookDaoImpl类

    1. public interface BookDao {
    2. public void save();
    3. }
    1. public class BookDaoImpl implements BookDao {
    2. public void save() {
    3. System.out.println("book dao save ..." );
    4. }
    5. }
    • 创建运行类App

    1. public class App {
    2. public static void main(String[] args) {
    3. ApplicationContext ctx = new
    4. ClassPathXmlApplicationContext("applicationContext.xml");
    5. BookDao bookDao = (BookDao) ctx.getBean("bookDao");
    6. bookDao.save();
    7. }
    8. }

    最终创建好的项目结构如下:

    2.容器  

    1.容器的创建方式

    案例中创建ApplicationContext的方式为:

    1. ApplicationContext ctx = new
    2. ClassPathXmlApplicationContext("applicationContext.xml");

    这种方式翻译为:类路径下的XML配置文件

    除了上面这种方式,Spring还提供了另外一种创建方式为:

    1. ApplicationContext ctx = new
    2. FileSystemXmlApplicationContext("applicationContext.xml");

    这种方式翻译为:文件系统下的XML配置文件

    使用这种方式,运行,会出现如下错误:

    从错误信息中能发现,这种方式是从项目路径下开始查找applicationContext.xml配置文件的,所 以需要将其修改为:对应的绝对路径

     说明:大家练习的时候,写自己的具体路径。 这种方式虽能实现,但是当项目的位置发生变化后,代码也需要跟着改,耦合度较高,不推荐使用。

    2.Bean的三种获取方式

    方式一,就是目前案例中获取的方式:

     BookDao bookDao = (BookDao) ctx.getBean("bookDao");

    这种方式存在的问题是每次获取的时候都需要进行类型转换,有没有更简单的方式呢?

    方式二:

    BookDao bookDao = ctx.getBean("bookDao",BookDao.class);

    这种方式可以解决类型强转问题,但是参数又多加了一个,相对来说没有简化多少。

    方式三:

     BookDao bookDao = ctx.getBean(BookDao.class);

    这种方式就类似我们之前所学习依赖注入中的按类型注入。必须要确保IOC容器中该类型对应的bean对象只能有一个。

    3.容器类层次结构

    (1)在IDEA中双击shift ,输入BeanFactory

     (2)点击进入BeanFactory类,ctrl+h,就能查看到如下结构的层次关系

    从图中可以看出,容器类也是从无到有根据需要一层层叠加上来的,大家重点理解下这种设计思想。

    4.BeanFactory的使用

    使用BeanFactory来创建IOC容器的具体实现方式为:

    1. public class AppForBeanFactory {
    2. public static void main(String[] args) {
    3. Resource resources = new ClassPathResource("applicationContext.xml");
    4. BeanFactory bf = new XmlBeanFactory(resources);
    5. BookDao bookDao = bf.getBean(BookDao.class);
    6. bookDao.save();
    7. }
    8. }
    为了更好的看出 BeanFactory ApplicationContext 之间的区别,在 BookDaoImpl 添加如下构造
    函数 :
    1. public class BookDaoImpl implements BookDao {
    2. public BookDaoImpl() {
    3. System.out.println("constructor");
    4. }
    5. public void save() {
    6. System.out.println("book dao save ..." );
    7. }
    8. }
    如果不去获取 bean 对象,打印会发现:
    • BeanFactory是延迟加载,只有在获取bean对象的时候才会去创建
    • ApplicationContext是立即加载,容器加载的时候就会创建bean对象
    • ApplicationContext要想成为延迟加载,只需要按照如下方式进行配置
    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="
    5. http://www.springframework.org/schema/beans
    6. http://www.springframework.org/schema/beans/spring-beans.xsd">
    7. <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" lazyinit="true"/>
    8. beans>

    3.核心容器总结

    1.容器相关

    容器创建的两种方式
    • ClassPathXmlApplicationContext[掌握]
    • FileSystemXmlApplicationContext[知道即可]
    获取 Bean 的三种方式
    • getBean("名称"):需要类型转换
    • getBean("名称",类型.class):多了一个参数
    • getBean(类型.class):容器中不能有多个该类的bean对象
    上述三种方式,各有各的优缺点,用哪个都可以。
    容器类层次结构
    • 只需要知晓容器的最上级的父接口为 BeanFactory即可
    BeanFactory
    • 使用BeanFactory创建的容器是延迟加载
    • 使用ApplicationContext创建的容器是立即加载
    • 具体BeanFactory如何创建只需要了解即可。

    2.bean相关

     其实整个配置中最常用的就两个属性idclass

    scope init-method destroy-method 框起来的原因是,后面注解在讲解的时候还会用到,
    所以大家对这三个属性关注下。

    3.依赖注入相关

    笔记来自:黑马程序员SSM框架教程

    四、图书推荐

      《Windows PowerShell自动化运维大全》由微软最有价值专家、微软TechEd优秀讲师徐鹏著作,多年经验毫无保留分享,一本书完全讲透Windows PowerShell自动化运维所有核心知识点,赠送同步视频学习教程,助你从运维初级工程师转向高级运维工程师!一本书精通Windows PowerShell自动化运维!

    本书从基础的 PowerShell 命令开始,先后讲述了基础命令、模块、脚本的编写等相关知识。同时为了让大家更快地理解和掌握 PowerShell 的环境配置和编写,我们使用系统内置的 PowerShell ISE 开发环境进行 PowerShell 代码的开发和运行。为了照顾很多基础薄弱的读者,在进行代码案例演示时都使用了 15 行以内的代码。

    本书可作为学校培训与企业培训的基本学习教程和工具书,相信通过本书的学习,读者可以更快地理解 PowerShell在日常生活及企业内的应用,为读者在自动化运维的道路上助力。

    徐鹏,微软最有价值专家、微软TechEd优秀讲师、《PowerQuery从入门到精通》作者。先后就职于宏基企业服务部、微软中国有限公司,为多家全球500强企业提供微软全系列产品培训、顾问咨询及架构优化服务。

     

    🍓本次送 3 本书 ,评论区抽3位小伙伴送书🍓

    活动时间:截止到 2023-05-02 14:00:00

    抽奖方式:利用程序进行抽奖。

    参与方式:关注博主、点赞、收藏,评论区评论 "五一假期,码不停息!"

    迫不及待的小伙伴也可以访问下面的链接了解详情:

    京东自营链接:Windows PowerShell自动化运维大全

    🍓 获奖名单🍓

    木梓辛铭

    洁洁!

    Tom·猫

    名单公布时间: 2023-05-02 14:00:00

  • 相关阅读:
    uni-app的来龙去脉,技术要点及技术难点,语法结构及应用场景,其实前端也很难,顶级的前端比后端都重要,感觉第一,理性第二
    易点易动助力企业设备高效管理,提升设备利用率
    离散数学 --- 特殊图 --- 欧拉图,哈密顿图
    redux-thunk 简单案例,优缺点和思考
    java毕业设计——基于java+JSP+MyEclipse的网上订餐系统设计与实现——网上订餐系统
    C语言理论--笔试面试基础稳固
    Go,从命名开始!Go的关键字和标识符全列表手册和代码示例!
    在 Rocky 中使用 FreeRDP 远程连接 Windows 机器
    零基础html学习/刷题-第一期
    ClickHouse MaterializeMySQL引擎
  • 原文地址:https://blog.csdn.net/Javascript_tsj/article/details/130160016