Spring框架
基于JavaEE的轻量级框架,使用spring可以降低模块的耦合度,提高开发效率。
Spring框架的两大核心技术:
IOC
IOC:控制反转
DI:依赖注入
AOP
面向切面编程
Spring的模块划分:
Spring IOC
Spring AOP
SpringJDBC (Spring + MyBatis)
Spring事务
Spring作用
Dao层 (数据访问层)
数据库的JDBC操作
对应的框架:MyBatis 或 Hibernate(持久层框架)
Service层 (业务逻辑层)
具体的业务逻辑处理
目前没有合适的框架
Spring框架不是用来处理业务逻辑层的
Controller层 (控制层)
Servlet:接收请求、响应数据、请求转发等
对应的框架:SpringMVC
Spring框架:
Bean对象的实例化
配置管理
面向切面编程
自带服务:
定时调度(定时任务)
邮件发送
集成第三方框架
Quartz时钟框架(定时调度)
Spring Security 权限框架
Spring环境搭建
-
创建普通的Maven项目 (修改pom.xml配置文件)
-
在pom.xml中引入spring框架的依赖坐标
-
创建Bean对象
-
在resources目录下新建spring.xml配置文件,并设置bean标签
-
设置bean标签的id与class属性值 (id是bean对象的唯一标签,class是bean对象的类对象)
-
得到spring的上下文环境,通过getBean方法得到指定id的bean对象
Spring IOC容器Bean对象实例化模拟实现
-
工厂模式
-
反射 (得到指定方法 得到指定字段 调用方法 实例化类)
-
XML解析 (dom4j + xpath)
-
单例模式
-
策略模式 (加载配置文件)
Spring IOC容器Bean对象实例化
构造器实例化
通过空构造进行Bean对象的实例化,要求Bean对象提供空构造
<bean id="唯一标识" class="类路径"> </bean>
静态工厂实例化 (了解)
-
定义静态工厂类 (普通类)
-
在类中定义静态方法,静态方法返回Bean对象的实例对象
-
在xml配置文件中通过静态工厂类得到实例化对象
<bean id="唯一标识" class="静态工厂类的类路径" factory-method="静态工厂类中的静态方法"> </bean>
实例工厂实例化(了解)
-
定义工厂类 (普通类)
-
在类中定义方法,方法返回Bean对象的实例对象
-
在xml配置文件中,先实例化工厂类
-
通过调用工厂类的方法,得到实例化对象
<bean id="工厂类的唯一标识" class="工厂类的类路径"></bean> <bean id="Bean对象的唯一标识" factory-bean="工厂类的唯一标识" factory-method="工厂类中的方法"></bean>
Spring IOC容器配置文件的加载
单配置文件加载
相对路径
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml"); BeanFactory ac = new ClassPathXmlApplicationContext("spring.xml");
绝对路径(了解)
ApplicationContext ac = new FileSystemXmlApplicationContext("配置文件的绝对路径");
多配置文件加载
可变参数
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml","配置文件名","");
import导入
在一个总的配置文件中导入其他需要加载的配置文件,加载配置文件时只需要加载总的配置文件
spring.xml
<bean id="" class=""></bean>
bean.xml
<bean id="" class=""></bean>
service.xml
<!-- 导入其他配置文件 --> <import resource="spring.xml"/> <import resource="bean.xml"/>
BeanFactory ac = new ClassPathXmlApplicationContext("service.xml");
Spring IOC注入
手动注入
set方法注入
需要提供set方法
public class UserService {private UserDao userDao; public void setUserDao(UserDao userDao) {this.userDao = userDao;} }
设置属性字段的值
<bean id="userService" class="com.shsxt.service.UserService"><!-- 通过property标签设置字段的值name:属性字段的名称 (setXXX)ref:指定的bean标签的id--><property name="userDao" ref="userDao" /> </bean> <bean id="userDao" class="com.shsxt.dao.UserDao"> </bean>
构造器注入
通过构造器的参数注入
public class UserService {private UserDao userDao; // 带参构造public UserService(UserDao userDao) {this.userDao = userDao;} }
设置属性字段的值
<bean id="userService" class="com.shsxt.service.UserService"><!-- 通过constructor-arg标签设置字段的值name:属性字段的名称ref:指定的bean标签的id--><constructor-arg name="" ref=""/> </bean> <bean id="userDao" class="com.shsxt.dao.UserDao"> </bean>
循环依赖问题
当两个或多个类需要互相注入时,构造器注入会出现循环依赖问题。可以通过set方法注入解决。
静态工厂注入 (了解)
实例化工厂注入 (了解)
自动注入
环境准备
-
在xml配置文件中引入context的命名空间及规范
-
开启自动注入
<context:annoation-config />
-
在需要注入的属性字段上添加注解 (属性字段是JavaBean)
@Resource
-
默认根据id属性值查找 (属性字段名与id属性值保持一致)
-
如果id属性值不一致,则会根据(Class)类型查找
-
注解可以声明在属性字段级别 或 set方法级别
-
属性字段可以提供set方法,也可以不提供
-
注解可以通过name属性设置别名,如果设置了name属性,就必须要求name属性与bean标签的id属性值一致
-
当一个对象有一个接口实现时,正常使用;如果有多个接口实现时,需要使用name设置别名
@Autowired
-
默认根据(Class)类型查找,与id属性值无关
-
注解可以声明在属性字段级别 或 set方法级别
-
属性字段可以提供set方法,也可以不提供
-
可以结合@Qualifier设置别名,需要设置@Qualifier的name属性值,name属性值与bean标签的id属性值一致
Spring IOC 扫描器
作用:
统一管理Bean,简化配置文件,提高开发效率
环境准备:
在配置文件中开启扫描器,并设置扫描范围
<context:componet-scan base-package="需要扫描的包目录"/>
注解:
声明在类级别
Controller层@Controller Service层@Service Dao层@Repository 任意类@Componet
Spring IOC Bean作用域与生命周期
Bean作用域
Spring IOC容器实例化的Bean'对象时单例对象!
单例作用域
当IOC容器实例化Bean对象时,会将实例化的Bean对象设置单例缓存池中,下次再从缓存池中获取
lazy-init懒加载
如果设置true,表示懒加载,IOC容器加载时,不进行Bean对象的实例化,而是在使用Bean对象时进行实例化
如果设置false,表示不懒加载,IOC容器加载时就实例化Bean对象,默认值
lazy-init懒加载为什么要设置为false?
1. 可以提前发现一些潜在的配置文件 2. IOC容器加载时会将Bean对象实例化,使用时不需在实例化,可以提高开发效率
什么对象适合作为单例?
无状态 或状态不可改变的对象
什么是无状态 或状态不可改变的对象?
不存在改变当前对象状态的成员变量。例:controller层、Service层、dao层
原型作用域
当IOC容器实例化Bean对象时,每次都会创建一个新的Bean对象
Web容器中的作用域
request作用域
session作用域
Bean的生命周期
Bean的定义
Bean的初始化
Bean的使用
Bean的销毁
IOC/DI
IOC/DI:控制反转/依赖注入
控制反转:将对象的创建过程转交给外部容器(IOC容器)来实现
依赖注入:给属性字段赋值 (JavaBean对象)
Spring AOP
代理模式
为一个委托类(目标对象)提供一个代理类(代理对象)
作用:可以通过代理对象实现目标对象的行为,并对目标对象的行为进行增强
两个原则:
1. 目标对象与代理对象有共同的行为 2. 代理对象增强目标对象
三要素:
1. 共同的行为 2. 目标对象 3. 代理对象
常见代理模式:
静态代理
动态代理
静态代理
1. 目标对象固定 2. 在程序运行前已经得到目标对象 3. 对目标对象进行增强 4. 当需要大量代理类是,可能会产生"类爆炸"
动态代理
在程序运行时,通过反射机制动态生成代理对象
JDK动态代理
注:要求目标对象有接口实现
通过Proxy类的newProxyInstance()得到代理对象
Object proxy = Proxy.newProxyInstance(类加载器, 接口数组, InvocationHandler接口);
InvocationHandler接口中有invoke方法,代理过程在invoke方法中执行
当代理对象调用方法时,即会执行invoke方法
CGLIB动态代理
注:采用继承思想,定义代理类继承目标类。目标类不能使用final修饰。
需要在pom.xml引入cglib的依赖。
通过Enhancer的create方法,可以生成一个类,并设置该类的父类为目标类。
通过设置Enhancer对象的Callback方法,在callback方法中实现代理过程。
利用MethodInterceptor接口,该接口是Callback的子接口。
Enhancer enhancer = new Enhancer(); // 设置目标类为父类 enhancer.setSuperClass(target.getClass()); // 设置代理过程 enhancer.setCallBack(MethodInterceptor接口); // 生成类 Object proxy = enhancer.create();
MethodInterceptor接口接口中,一个intercept方法,代理过程在intercept方法中执行
当代理对象调用方法时,即会执行intercept方法