基于XML的Spring使用
一、Spring IOC 底层实现
IOC:将对象的控制器反转给Spring
1.1 BeanFactory与ApplicationContexet
BeanFactory
:IOC容器的基本实现,是Spring内部的使用接口,是面向Spring本身的,不是提供给开发人员使用的。****ApplicationContext
:BeanFactory的子接口,提供了更多高级特性。面向Spring的使用者,几乎所有场合都使用ApplicationContext而不是底层的BeanFactory。
1.2 图解IOC类的结构
BeanFactory
:Spring底层IOC实现【面向Spring框架】- …
ApplicationContext
:面向程序员- ConfigurableApplicationContext:提供关闭或刷新容器对象方法
- …
- ClassPathXmlApplicationContext:基于类路径检索xml文件
- AnnotationConfigApplicationContext:基于注解创建容器对象
- FileSystemXmlApplicationContext:基于文件系统检索xml文件
- …
- ConfigurableApplicationContext:提供关闭或刷新容器对象方法
- …
二、 Spring依赖注入数值问题【重点】
2.1 字面量数值
- 数据类型:基本数据类型及包装类、String
- 语法:value属性或value标签
2.2 CDATA区
- 语法:
<![CDATA[]]>
- 作用:在
xml(mybatis / spring)
中定义特殊字符时,使用CDATA区
2.3 外部已声明bean及级联属性赋值
-
语法:
ref=
-
注意:级联属性更改数值会影响外部声明bean
【ref赋值的是引用】
-
示例代码
<bean id="dept1" class="com.atguigu.pojo.Dept"> <property name="deptId" value="1"></property> <property name="deptName" value="研发部门"></property> </bean> <bean id="empChai" class="com.atguigu.pojo.Employee"> <property name="id" value="101"></property> <property name="lastName" value="chai"></property> <property name="email" value="chai@163.com"></property> <property name="salary" value="50.5"></property> <property name="dept" ref="dept1"></property> <property name="dept.deptName" value="财务部门"></property> </bean>
2.4 内部bean
-
概述
- 内部类:在一个类中完整定义另一个类,当前类称之为内部类
- 内部bean:在一个bean中完整定义另一个bean,当前bean称之为内部bean
-
注意:内部bean不会直接装配到IOC容器中
-
示例代码
<!-- 测试内部bean--> <bean id="empXin" class="com.atguigu.pojo.Employee"> <property name="id" value="102"></property> <property name="lastName" value="xx"></property> <property name="email" value="xx@163.com"></property> <property name="salary" value="51.5"></property> <property name="dept"> <bean class="com.atguigu.pojo.Dept"> <property name="deptId" value="2"></property> <property name="deptName" value="人事部门"></property> </bean> </property> </bean>
2.5 集合
-
List
<!-- 测试集合--> <bean id="dept3" class="com.atguigu.pojo.Dept"> <property name="deptId" value="3"></property> <property name="deptName" value="程序员鼓励师"></property> <property name="empList"> <list> <!-- 第一种方式 --> <ref bean="empChai"></ref> <ref bean="empXin"></ref> <!-- 第二种方式 --> <!-- <bean></bean> --> </list> </property> </bean> <!-- 测试提取List 之后再 ref 引用 --> <util:list id="empList"> <ref bean="empChai"></ref> <ref bean="empXin"></ref> </util:list> <bean id="dept4" class="com.atguigu.pojo.Dept"> <property name="deptId" value="4"></property> <property name="deptName" value="运营部门"></property> <property name="empList" ref="empList"></property> </bean>
-
Map
<!-- 测试Map--> <bean id="dept5" class="com.atguigu.pojo.Dept"> <property name="deptId" value="5"></property> <property name="deptName" value="采购部门"></property> <property name="empMap"> <map> <!-- 第一种方式 --> <entry key="101" value-ref="empChai"></entry> <!-- 第二种方式 --> <entry> <key><value>103</value></key> <ref bean="empChai"></ref> </entry> <entry> <key><value>102</value></key> <ref bean="empXin"></ref> </entry> </map> </property> </bean> <!-- 测试提取Map 之后再 ref 引用 --> <util:map id="empMap"> <entry key="101" value-ref="empChai"></entry> <entry> <key><value>103</value></key> <ref bean="empChai"></ref> </entry> <entry> <key><value>102</value></key> <ref bean="empXin"></ref> </entry> </util:map> <bean id="dept6" class="com.atguigu.pojo.Dept"> <property name="deptId" value="106"></property> <property name="deptName" value="后勤部门"></property> <property name="empMap" ref="empMap"></property> </bean>
三、 Spring依赖注入方式【基于XML】
为属性赋值方式
- 通过xxxset()方法
- 通过构造器
- 反射
3.1 set注入
- 语法:
<property>
3.2 构造器注入
- 语法:
<constructor-arg>
3.3 p名称空间注入
导入名称空间:xmlns:p=“http://www.springframework.org/schema/p”
- 语法:
<bean p:xxx>
3.4 示例代码
<bean id="stuZhouxu" class="com.atguigu.spring.pojo.Student">
<property name="stuId" value="102"></property>
<property name="stuName">
<value><![CDATA[<<zhouxu>>]]></value>
</property>
</bean>
<bean id="stuZhiFeng" class="com.atguigu.spring.pojo.Student">
<constructor-arg name="stuId" value="103"></constructor-arg>
<constructor-arg name="stuName" value="zhifeng"></constructor-arg>
</bean>
<bean id="stuXiaoxi"
class="com.atguigu.spring.pojo.Student"
p:stuId="104"
p:stuName="xiaoxi"></bean>
四、 Spring管理第三方bean
4.1 Spring管理druid步骤
druid:数据库连接池。参考:Java:JDBC的使用
-
导入jar包
<!--导入druid的jar包--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency> <!--导入mysql的jar包--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.37</version> <!-- <version>8.0.26</version>--> </dependency>
-
编写db.properties配置文件
#key=value db.driverClassName=com.mysql.jdbc.Driver db.url=jdbc:mysql://localhost:3306/db220106 db.username=root db.password=root
-
编写applicationContext.xml相关代码
<!-- 加载外部属性文件db.properties--> <context:property-placeholder location="classpath:db.properties"></context:property-placeholder> <!-- 装配数据源--> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${db.driverClassName}"></property> <property name="url" value="${db.url}"></property> <property name="username" value="${db.username}"></property> <property name="password" value="${db.password}"></property> </bean>
-
测试
@Test public void testDruidDataSource() throws Exception{ //获取容器对象 ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext_druid.xml"); DruidDataSource dataSource = ioc.getBean("dataSource", DruidDataSource.class); System.out.println("dataSource = " + dataSource); DruidPooledConnection connection = dataSource.getConnection(); System.out.println("connection = " + connection); }
五、 Spring中FactoryBean【了解】
5.1 Spring中两种bean
- 一种是普通bean
- 另一种是工厂bean【FactoryBean】
- 作用:如需我们程序员参数到bean的创建时,使用FactoryBean
5.2 FactoryBean使用步骤
- 实现FactoryBean接口
- 重写方法【三个】
- 装配工厂bean
- 测试
package com.atguigu.factory;
import com.atguigu.pojo.Dept;
import org.springframework.beans.factory.FactoryBean;
/**
* @author Chunsheng Zhang 尚硅谷
* @create 2022/3/26 14:09
*/
public class MyFactoryBean implements FactoryBean<Dept> {
/**
* getObject():参数对象创建的方法
* @return
* @throws Exception
*/
@Override
public Dept getObject() throws Exception {
Dept dept = new Dept(101,"研发部门");
//.....
return dept;
}
/**
* 设置参数对象Class
* @return
*/
@Override
public Class<?> getObjectType() {
return Dept.class;
}
/**
* 设置当前对象是否为单例
* @return
*/
@Override
public boolean isSingleton() {
return true;
}
}
六 Spring中bean的作用域
6.1 语法
- 在bean标签中添加属性:scope属性即可
6.2 四个作用域
- singleton【默认值】:单例【在容器中只有一个对象】
- 对象创建时机:创建容器对象时,创建对象执行
- prototype:多例【在容器中有多个对象】
- 对象创建时机:getBean()方法被调用时,创建对象执行
- request:请求域
- 当前请求有效,离开请求域失效
- 当前请求:URL不变即为当前请求
- session:会话域
- 当前会话有效,离开当前会话失效
- 当前会话:当前浏览不关闭不更换即为当前会话
七、 Spring中bean的生命周期
7.1 bean的生命周期
① 通过构造器或工厂方法创建bean实例
② 为bean的属性设置值和对其他bean的引用
③ 调用bean的初始化方法
④ bean可以使用了
⑤ 当容器关闭时,调用bean的销毁方法
7.2 bean的后置处理器
-
作用:在调用初始化方法前后对bean进行额外的处理。
-
实现:
- 实现BeanPostProcessor接口
- 重写方法
- postProcessBeforeInitialization(Object, String):在bean的初始化之前执行
- postProcessAfterInitialization(Object, String):在bean的初始化之后执行
- 在容器中装配后置处理器
-
注意:装配后置处理器会为当前容器中每个bean均装配,不能为局部bean装配后置处理器
7.3 添加后置处理器后bean的生命周期
① 通过构造器或工厂方法创建bean实例
② 为bean的属性设置值和对其他bean的引用
postProcessBeforeInitialization(Object, String):在bean的初始化之前执行
③ 调用bean的初始化方法
postProcessAfterInitialization(Object, String):在bean的初始化之后执行
④ bean可以使用了
⑤ 当容器关闭时,调用bean的销毁方法
八、 Spring中自动装配【基于XML】
8.1 Spring中提供两种装配方式
- 手动装配
- 自动装配
8.2 Spring自动装配语法及规则
-
在bean标签中添加属性:Autowire即可
-
byName:对象中属性名称与容器中的beanId进行匹配,如果属性名与beanId数值一致,则自动装配成功
-
byType:对象中属性类型与容器中class进行匹配,如果唯一匹配则自动装配成功
-
匹配0个:未装配
-
匹配多个,会报错
expected single matching bean but found 2: deptDao,deptDao2
-
-
-
注意:基于XML方式的自动装配,只能装配非字面量数值
8.3 总结
- 基于xml自动装配,底层使用set注入
- 最终:不建议使用byName、byType,建议使用注解方式自动装配