Spring框架概述
- 百度一堆,不细说
- 核心 IOC,AOP
控制反转IOC,面向切面AOP
控制反转,对象创建和对象之间的调用过程交给spring进行管理
- 使用ioc目的:降低耦合度
- 底层原理 xml解析,工厂模式,反射
-
IOC接口 (BeanFactory接口
ioc 思想基于ioc容器完成,ioc容器底层就是对象工厂
- Spring提供ioc容器两种实现 两个接口
- BeanFactory: ioc容器的基本实现,是spring内部使用接口,不提供给开发人员进行使用
- 注意: 加载配置文件的时候不会创建对象,而是在获取对象(使用)的时候才去创建对象
- ApplicationContext: BeanFactory 的自接口,提供更多更强大的实现,一般由开发人员进行使用
- 注意:加载配置文件的时候就会吧配置文件中的bean对象进行创建 ```java @Test public void testBean(){ // 1 加载spring的配置文件 // 两种方式皆可,但是区别如上, ApplicationContext context = new ClassPathXmlApplicationContext(“bean1.xml”); BeanFactory context1 = new ClassPathXmlApplicationContext(“bean1.xml”); // 2 获取配置创建的对象 // User user = context.getBean(“user”, User.class); UserService userService = context.getBean(“userService”, UserService.class); userService.add(); }
- BeanFactory: ioc容器的基本实现,是spring内部使用接口,不提供给开发人员进行使用
<a name="v6Xki"></a>
### ApplicationContext接口的两个实现类

- 简要区别 FileSystem 开头的,按照文件系统的绝对路径,ClassPath 按照项目的相对路径。
- 调用不同则决定去寻找xml配置文件的方式不同。
<a name="WqT6N"></a>
# IOC操作 Bean 管理 概念
- 什么是bean的管理
- bean的管理指的是两个操作
- spring创建对象
- spring注入属性
- bean管理操作两种方式 如下
<a name="ALu7r"></a>
## IOC 操作 Bean 管理 基于XML
<a name="B1bk2"></a>
### 基于xml方式创建对象
```java
<!-- 配置user对象创建 -->
<bean id="user" class="com.addicated.spring5.User"></bean>
- spring配置文件中使用bean标签,标签里面添加对应属性,实现对象创建
- 在bean标签有很多属性,下面介绍常用
- id 属性 : 唯一表示 web.xml下唯一
- class 属性: 全类名,用于底层反射进行类对象创建
-
基于xml方式注入属性
-
传统方式
```java /**
- 演示使用 set 方法进行注入属性
*/
public class Book {
//创建属性
private String bname;
private String bauthor;
//创建属性对应的 set 方法
public void setBname(String bname) {
this.bname = bname;
}
public void setBauthor(String bauthor) {
this.bauthor = bauthor;
} }
<a name="KKg31"></a> #### spring的xml 注入 通过set ```java <!--2 set 方法注入属性--> <bean id="book" class="com.atguigu.spring5.Book"> <!--使用 property 完成属性注入 name:类里面属性名称 value:向属性注入的值 --><property name="bname" value="易筋经"></property> <property name="bauthor" value="达摩老祖"></property> </bean>
注意:需要注入的bean中提供set方法,原因不再赘述,文章一开头已经指出
spring的xml注入 通过有参数构造
创建类,定义属性,创建有参数构造器
<!--3 有参数构造注入属性--> <bean id="orders" class="com.atguigu.spring5.Orders"> <constructor-arg name="oname" value="电脑"></constructor-arg> <constructor-arg name="address" value="China"></constructor-arg> </bean>
spring的xml注入 p空间注入 了解
```java <?xml version=”1.0” encoding=”UTF-8”?>
```java
(1)使用 p 名称空间注入,可以简化基于 xml 配置方式
第一步 添加 p 名称空间在配置文件中
第二步 进行属性注入,在 bean 标签里面进行操作
<!--2 set 方法注入属性--> <bean id="book" class="com.atguigu.spring5.Book" p:bname="九阳神功"
p:bauthor="无名氏"></bean>
spring的xml注入 其他类型属性
- 字面量 与 特殊字符 避免转义
- null值
```java
演示null值注入 <![CDATA[<<测试字符>>]]]>
- null值
```java
</bean>
<a name="UlwVM"></a>
#### spring的xml注入属性 外部bean
- 创建两个类 service 和dao
- 在service 中调用dao里面的方法
- 在spring配置文件中进行配置
```java
---- service
package com.addicated.spring5.service;
import com.addicated.spring5.dao.UserDao;
public class UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void add(){
System.out.println("添加用户");
userDao.update();
}
}
-- dao
package com.addicated.spring5.dao;
public interface UserDao {
public void update();
}
--- daoimpl
package com.addicated.spring5.dao;
public class UserDaoImpl implements UserDao {
@Override
public void update() {
System.out.println("userdao接口的update方法得到了调用");
}
}
- spring中xml
```java
- 相当于在一个bean内通过ref吧另外一个bean对象关联进来,关联的bean要提供其的set方法
<a name="DPbvy"></a>
#### spring的xml注入属性 内部bean
- 案例
- 一对多关系:部门和员工
- 一个部门有多个与昂工,一个员工属于一个部门
- 部门为1,员工为多
- 实体类中表示1对多关系。
```java
---- Dept
package com.addicated.spring5.dept;
public class Dept {
private String dname;
public void setDname(String dname) {
this.dname = dname;
}
}
---- Emp
package com.addicated.spring5.dept;
public class Emp {
private String eName;
private String gender;
// 员工属于某一个部门,使用对象的形式进行表示
private Dept dept;
public void setDept(Dept dept) {
this.dept = dept;
}
public void seteName(String eName) {
this.eName = eName;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Emp{" +
"eName='" + eName + '\'' +
", gender='" + gender + '\'' +
", dept=" + dept +
'}';
}
}
- spring 配置 简单理解,bean中bean
```java
<a name="WcYCU"></a>
#### spring的xml注入属性 级联赋值
- 相当于引如外部bean 然后再进行修改赋值
```java
<bean id="emp" class="com.atguigu.spring5.bean.Emp">
<!--设置两个普通属性-->
<property name="ename" value="lucy"></property>
<property name="gender" value="女"></property>
<!--级联赋值-->
<property name="dept" ref="dept"></property>
这种方式需要 在对应bean内 提供要设置的目标bean的get方法,否则会找不到要设置属性的bean,会覆盖外部bena的值
<property name="dept.dname" value="技术部"></property>
</bean>
<bean id="dept" class="com.atguigu.spring5.bean.Dept">
<property name="dname" value="财务部"></property>
</bean>
spring的xml 注入集合属性
- 注入数组类型属性
- 注入List集合类型属性
注入Map集合类型属性
- 创建类,定义数组,list,map,set类型属性,生成set方法
public class Stu { //1 数组类型属性 private String[] courses; //2 list 集合类型属性 private List<String> list; //3 map 集合类型属性 private Map<String,String> maps; //4 set 集合类型属性 private Set<String> sets; public void setSets(Set<String> sets) { this.sets = sets; } public void setCourses(String[] courses) { this.courses = courses; } public void setList(List<String> list) { this.list = list; } public void setMaps(Map<String, String> maps) { this.maps = maps; } }
- 创建类,定义数组,list,map,set类型属性,生成set方法
编写xml进行属性注入
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--1 集合类型属性注入--> <bean id="stu" class="com.atguigu.spring5.collectiontype.Stu"> <!--数组类型属性注入--> <property name="courses"> <array> <value>java课程</value> <value>数据库课程</value> </array> </property> <!--list类型属性注入--> <property name="list"> <list> <value>张三</value> <value>小三</value> </list> </property> <!--map类型属性注入--> <property name="maps"> <map> <entry key="JAVA" value="java"></entry> <entry key="PHP" value="php"></entry> </map> </property> <!--set类型属性注入--> <property name="sets"> <set> <value>MySQL</value> <value>Redis</value> </set> </property> <!--注入list集合类型,值是对象--> <property name="courseList"> <list> <ref bean="course1"></ref> <ref bean="course2"></ref> </list> </property> </bean> <!--创建多个course对象--> <bean id="course1" class="com.atguigu.spring5.collectiontype.Course"> <property name="cname" value="Spring5框架"></property> </bean> <bean id="course2" class="com.atguigu.spring5.collectiontype.Course"> <property name="cname" value="MyBatis框架"></property> </bean> </beans>
在集合里面设置对象类型
<!--注入list集合类型,值是对象--> <property name="courseList"> <list> <ref bean="course1"></ref> <ref bean="course2"></ref> </list> </property> </bean> <!--创建多个course对象--> <bean id="course1" class="com.atguigu.spring5.collectiontype.Course"> <property name="cname" value="Spring5框架"></property> </bean> <bean id="course2" class="com.atguigu.spring5.collectiontype.Course"> <property name="cname" value="MyBatis框架"></property> </bean>
集合注入提取
IOC 操作Bean 管理(FactoryBean)
spring中有两种bean ,一种普通bean,另外一种工厂bean (factoryBean
- 普通bean , 在配置文件中定义bean类型就是返回类型
- 工厂bean 在配置文件定义bean类型可以和返回类型不一样
- 第一步 创建类,让这个类作为工厂bean,实现接口FactoryBean
- 第二部 实现接口里面的方法 ```java package com.atguigu.spring5.factorybean;
import com.atguigu.spring5.collectiontype.Course; import org.springframework.beans.factory.FactoryBean;
public class MyBean implements FactoryBean
//定义返回bean
@Override
public Course getObject() throws Exception {
Course course = new Course();
course.setCname("abc");
return course;
}
@Override
public Class<?> getObjectType() {
return null;
}
@Override
public boolean isSingleton() {
return false;
}
}
@Test public void test3() { ApplicationContext context = new ClassPathXmlApplicationContext(“bean3.xml”); // 这里是因为上面实现 FacotryBean的时候定义了返回的bean类型 Course course = context.getBean(“myBean”,Course.class); System.out.println(course); }
<a name="hrOCj"></a>
## IOC操作Bean 作用域
- spring中,默认情况下 bean是单实例对象
```java
@Test
public void testSpring(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
Stu stu = context.getBean("Stu", Stu.class);
Stu stu1 = context.getBean("Stu", Stu.class);
// 两个对象的hash值一致,代表默认单实例
System.out.println(stu.hashCode());
System.out.println(stu1.hashCode());
}
如何设置单例还是多例
singleton 单实例 prototype多实例
- 设置scope为 singleton 的时候,加载spring配置文件时就会创建单实例对象
设置scope为 prototype的时候,不是在加载Spring配置文件的时候创建对象,而是在调用getBean方法的时候创建多实例对象
IOC 操作 Bean 生命周期
生命周期
- 从对象创建到对象销毁的过程
- bean生命周期
- 通过构造器创建bean实例 无参构造器
- 为bean的属性设置值和对其他bean进行引用 调用set方法
- 调用bean的初始化方法 需要在配置中进行配置
- bean可以使用了 (代表对象获取到了
- 当容器关闭的时候,调用bean的销毁方法(同样需要在配置中进行配置 ```java package com.addicated.bean_;
public class Orders {
//无参数构造
public Orders() {
System.out.println("第一步 执行无参数构造创建bean实例");
}
private String oname;
public void setOname(String oname) {
this.oname = oname;
System.out.println("第二步 调用set方法设置属性值");
}
//创建执行的初始化的方法
public void initMethod() {
System.out.println("第三步 执行初始化的方法");
}
//创建执行的销毁的方法
public void destroyMethod() {
System.out.println("第五步 执行销毁的方法");
}
}
@Test
public void testMyBean1(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
// MyBean myBean = context.getBean(“myBean”, MyBean.class); Orders myBean = context.getBean(“Orders”, Orders.class); System.out.println(myBean); context.close(); }

<a name="Wv73Q"></a>
### bean 的后置处理器
(1)通过构造器创建 bean 实例(无参数构造) <br />(2)为 bean 的属性设置值和对其他 bean 引用(调用 set 方法) <br />**(3)把 bean 实例传递 bean 后置处理器的方法 **postProcessBeforeInitialization <br />(4)调用 bean 的初始化的方法(需要进行配置初始化的方法)<br />**(5)把 bean 实例传递 bean 后置处理器的方法 **postProcessAfterInitialization <br />(6)bean 可以使用了(对象获取到了) <br />(7)当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)
<a name="kvpoq"></a>
### 实现
```java
package com.addicated.bean_;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.lang.Nullable;
import org.springframework.util.SocketUtils;
public class MyBeanPost implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在初始化之前执行的方法");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在初始化之后执行的方法");
return bean;
}
}
<!-- 配置后置处理器 -->
<bean id="MyBeanPost" class="com.addicated.bean_.MyBeanPost" >
</bean>
IOC 操作 Bean管理 xml自动装配
- * 之前在web.xml进行属性注入 都为手动
1 什么是自动装配
1)根据指定装配规则(属性名或者属性类型) Spring自动将陪陪的属性值进行注入
2 演示自动装配过程 ```java
<a name="N7Kel"></a>
## IOC 操作 Bean 管理 (外部属性文件引入
- 引入 context 命名空间,具体可百度
```java
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!--直接配置连接池-->
<!--<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/userDb"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>-->
<!--引入外部属性文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--配置连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${prop.driverClass}"></property>
<property name="url" value="${prop.url}"></property>
<property name="username" value="${prop.userName}"></property>
<property name="password" value="${prop.password}"></property>
</bean>
</beans>
----jdbc.properties 文件内容如下
prop.driverClass=com.mysql.jdbc.Driver
prop.url=jdbc:mysql://localhost:3306/userDb
prop.userName=root
prop.password=root