IoC/DI配置第三方bean
案例:数据源对象的管理
管理alibaba的druid数据源
新建一个工程,结构如下
首先需要在pro.xml文件中配置druid对象,添加相关依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
接着在配置文件中管理DruidSource对象
最后我们打印一下,看看有没有正常运行
运行结果,代码能够正常执行
管理c3p0的连接池对象
在maven仓库中找到c3p0,复制依赖代码,导入pro.xml文件中
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.10.1</version>
</dependency>
配置其bean对象
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring_db"/>
<property name="user" value="root"/>
<property name="password" value="root"/>
</bean>
最后能够成功初始化C3P0
key:
我们发现将用户名密码等信息写入bean文件并不方便,我们学习如何在Spring中将这些信息写入properties文件,并进行加载
首先我们新开一个命名空间NameSpace 叫做context
其次开启context命名空间,使用命名空间加载jdbc.properties文件(在resources目录下创建)
如何加载呢,将value后加上属性占位符${},在大括号写入properties内对应的属性名称
为了验证效果,我们创建一个BookDaoImpl实现类,利用set构造,并打印出相关信息。
如图:
通过这种方式,能验证通过properties 注入信息的有效性,打印
加载properties文件
为了避免加载的properties文件中命名与系统名冲突,我们可以在context 相关命令后加一条属性
加载properties文件中的一些坑
核心容器
创建容器
获取bean
程序中代码实现
容器内层次结构图
BeanFactory初始化
示例:
BeanFactory加载bean的方法,(作了解)
这种方式与 ApplicationContext ctx = new ClassPathXmlApplicationContext("file.xml");的区别在哪呢,区别在于用beanFactory加载,bean是延迟加载的,而用 ApplicationContext加载,bean是立刻加载的,我们做个实验,在BookServiceImpl中加上构造方法,在里面打印一句话
如果bean是立即加载的,那么这句话会被打印出来,然后我们将测试类中的获取bean对象以及调用方法相关代码删除,只留下加载bean的代码
然后我们分别运行,得到结果前者可以打印出constructor,说明ApplicationContext是立刻加载bean的,即它启动容器直接初始化完毕(默认加载无参构造)。
ApplicationContext中也可以实现延迟加载,只需在applicationContext.xml内加入代码即可
总结
红框为重点需掌握,其他了解即可
容器相关
bean相关
依赖注入相关
注解开发
注解开发定义bean(Spring2.5)
示例:创建一个工程,结构如下:
相关程序文件如下(由于我用的是JDK21,经过实验,用6.1.13版本的spring依赖可以适配):
然后我们用注解,取代在xml文件中用指定bean对象,具体方法,如下图所示
在步骤2中@component可以写成@component("bookDao"),因为我们扫描的包下只有写了这一个注解所以括号内可以不写
如果我们要在工程中,获取BookService类的bean对象,也采用注解方式,component中可以不用写bean的名称,可以采用BookService字节码文件 获取
所以,如果不想在@component后面带括号,用getBean()方法获取bean对象时候建议用实现类的字节码文件方式获取
最后,Spring为三个层定义了衍生注解,功能和@component完全一样,只是为了方便我们查看
纯注解开发(Spring3.0)
我们发现,用context后,配置类里面除了指定扫描的代码,其他代码相对固定冗余,于是Spring提供了一个 Configuration 注解,能够将注解代码写入类中。
我们创建配置类,在类中写入如下代码 @ComponentScan 括号内写的是扫描路径
然后我们在测试程序内,不再加载xml文件, 用新写的配置类来配置bean,写入以下程序
效果与用xml文件的效果完全一样
总结:
作用范围
注解开发生成一个新项目
运行App代码。
获得的地址相同,默认生成的是单例bean
想要更改为非单例,只需在实现类加上注解@scope("prototype")即可
这样生成的bean地址就不同了
生命周期
控制生命周期,首先需要在pro.xml中导入相关的包
接着在实现类中控制生命周期相关代码上加上注解
在主程序中加上关闭bean的代码
之后运行程序,就能看到相关注解起作用了
依赖注入---自动装配
Spring为了使用注解简化开发,提供了自动装配的注解实现
首先我们先创建一个工程文件,目录如下:
在pom.xml文件中添加以下依赖(jdk21)
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version> <!-- 使用最新版本 -->
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.1.13</version>
<scope>compile</scope>
</dependency>
</dependencies>
以下是工程的内容:
引用类型
自动注解只需在实现类BookServiceImpl中添加@Autowired注解,setBookDao()方法也可以省略,因为其内部是用的暴力反射对私有属性进行访问。
运行结果正常:
如果要实现两个数据层呢,有多个相同类型的bean,我们可以用bean名称来指定。创建一个新的BookDaoImpl2实现类,给@Repository 注解后面加上指定的bean名称,我们发现自动匹配了bookDao名称 ,虽然可以这么做,但是并不推荐
推荐使用@Qualifier注解 指定bean名称
利用@Qualifier注解 指定bean为bookDao2
运行后
简单类型
对于简单类型的引用,只要在类型前加上@Value(),括号内指定类型的值即可
注解中的信息,都可以通过外界的properties文件加载,所以和直接写进程序里面是又区别的
加载properties文件
步骤1 我们在resources下创建一个jdbc.properties,在里面写入name属性的值 name=itheima888
步骤2 在SpringConfig中写入@ProperSource注解,在里面指定properties文件
步骤3 将实现类中@Value注解内的值改为占位符 里面加上name属性
注:
第三方bean管理
创建一个新工程,工程里面只定义了SpringConfig,App对其进行了初始化
由于是第三方bean,无法将配置写入源代码中,只能编程去获取
关于Spring和JDBC的配置文件,分别写入SpringConfig和JdbcConfig类中
第一种写法(不推荐)
第二种:
对于配置文件中的简单类型依赖输入,我们可以通过@Value 导入
对于引用类型依赖注入,假设要引用bookDaoImpl类,只需打开包扫描,然后再配置文件中传入形参即可(自动装配)
总结
XML配置对比注解配置