概述
目录
- 一、IOC容器
- (一)什么是IOC
- (二)IOC底层原理
- (三)BeanFactory 接口
- 1、IOC思想
- 2、Spring 提供 IOC 容器实现两种方式
- (1)BeanFactory
- (2)ApplicationContext
- (四)基于注解进行bean管理
- 1、什么是注解
- 2、Spring 针对 Bean 管理中创建对象提供注解
- 3、基于注解方式实现对象创建
- (1)开启组件扫描
- (2)创建类,在类上面添加创建对象注解
- (3)属性的注入
- (4)完全注解开发
- (5)编写测试类
- (五)bean 作用域
- 1、scope
- 2、scope 属性值
- 3、singleton 和 prototype 区别
- (六)bean 生命周期
- 1、bean 生命周期
- 2、bean 的后置处理器,bean 生命周期有七步
- 3、最终生命周期
- 二、AOP
- (一)什么是AOP
- 1、面向切面编程(方面)
- 2、通俗描述
- 3、术语
- 4、通知的多种类型
- (二)切入点表达式
- (三)流程
- 1、创建要增强的类和增强类
- 2、开启注解扫描以及开启生成代理对象
- 3、生成两个类的bean对象
- 4、在增强类上面添加注解 @Aspect
- 5、配置不同类型的通知
- 6、设置增强类优先级
- 7、提取相同切入点表达式
- 8、执行结果
- 三、JdbcTemplate
- (一)什么是 JdbcTemplate
- (二)执行步骤(基于完全注解开发)
- 1、配置配置类
- 2、编写实体类
- 3、编写Service和DAO
- 4、编写测试类
- 5、修改和删除
- 6、查询返回某个值
- 7、查询返回对象
- 8、查询返回集合
- 9、批量操作
- 四、Spring中队事务的管理
- (一)什么事务
- (二)事务四个特性(ACID)
- (三)事务操作过程
- (四)Spring 事务管理介绍
- (五)具体操作
- 1、编写配置类(在上一个模块基础上)
- 2、在 service 类上面(或者 service 类里面方法上面)添加事务注解
- 3、对一些重要参数进行解释
- (1)propagation:事务传播行为
- (2)ioslation:事务隔离级别
- (3)timeout:超时时间
- (4)readOnly:是否只读
- (5)rollbackFor:回滚
- (6)noRollbackFor:不回滚
- 五、Spring5 框架新功能
- (一)代码整理
- (二)Spring 5.0 框架自带了通用的日志封装
- (三)Spring5 框架核心容器支持@Nullable 注解
- (四)Spring5 核心容器支持函数式风格GenericApplicationContext
- (五)Spring5 支持整合 JUnit5
- (六)SpringWebflux
一、IOC容器
(一)什么是IOC
①控制反转,把对象创建和对象之间的调用过程,交给 Spring 进行管理
②使用 IOC 目的:为了耦合度降低
(二)IOC底层原理
xml 解析、工厂模式、反射
(三)BeanFactory 接口
1、IOC思想
IOC思想基于IOC容器完成,IOC容器底层就是对象工厂(即BeanFactory 接口)
2、Spring 提供 IOC 容器实现两种方式
(1)BeanFactory
IOC 容器基本实现,是 Spring 内部的使用接口,不提供开发人员进行使用。
特点:加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象
(2)ApplicationContext
BeanFactory 接口的子接口,提供更多更强大的功能,一般由开发人员进行使用。
特点:加载配置文件时候就会把在配置文件对象进行创建
BeanFactory继承关系
(四)基于注解进行bean管理
1、什么是注解
注解是代码特殊标记
格式:@注解名称(属性名称=属性值, 属性名称=属性值…)
作用 在类上面,方法上面,属性上面
使用注解目的:简化 xml 配置,现在开发几乎都是用完全注解开发
2、Spring 针对 Bean 管理中创建对象提供注解
注解 | 用法 |
---|---|
@Component | 常用 |
@Service | 服务层 |
@Controller | 控制层 |
@Repository | DAO层 |
上面四个注解功能是一样的,都可以用来创建 bean 实例
3、基于注解方式实现对象创建
(1)开启组件扫描
在Spring配置文件中添加组件扫描,用来让Spring识别注解
<context:component-scan base-package="com.zichao.controller"/>
其中base-package为要开启组件扫描的包路径
(2)创建类,在类上面添加创建对象注解
@Controller
public class index {
public void open(){
System.out.println("我是控制层组件");
}
}
这样Spring容器就会加载index类的bean
(3)属性的注入
注意:进行属性注入时要提供对应属性的set方法
注解 | 说明 |
---|---|
@Autowired | 根据属性类型进行自动装配 |
@Qualifier | 根据名称进行注入,和@Autowired 一起使用 |
@Autowired | 可以根据类型注入,也可以根据名称注入 |
@Autowired | 注入普通类型属性 |
(4)完全注解开发
创建配置类,替代 xml 配置文件
@Configuration
@ComponentScan(basePackages = {"com.zichao"})
public class SpringConfig {
}
其中basePackages为开启组件扫描地址,为一个数组
(5)编写测试类
编写user类,作为属性传入
@Component
public class User {
public void test(){
System.out.println("我是user类");
}
}
编写index类,设置4个需要输入的属性
@Controller(value = "index" )
public class Index {
@Autowired
User user;
@Autowired
@Qualifier(value = "user")
User userQualifier;
@Resource
User userResource;
@Value(value = "我是String类型")
String userValue;
public void test(){
user.test();
userQualifier.test();
userResource.test();
System.out.println(userValue);
}
}
根据配置类,进行测试
public class TestIOC {
@Test
public void test01(){
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
Index index = applicationContext.getBean("index",Index.class);
index.test();
}
}
执行结果
(五)bean 作用域
在 Spring 里面,默认情况下,bean 是单实例对象
1、scope
在 spring 配置文件 bean 标签里面有属性(scope)用于设置单实例还是多实例
2、scope 属性值
第一个值 默认值,singleton,表示是单实例对象
第二个值 prototype,表示是多实例对象
3、singleton 和 prototype 区别
①设置 scope 值是 singleton 时候,加载 spring 配置文件时候就会创建单实例对象
②设置 scope 值是 prototype 时候,不是在加载 spring 配置文件时候创建 对象,在调用 getBean 方法时候创建多实例对象
(六)bean 生命周期
1、bean 生命周期
①通过构造器创建 bean 实例(无参数构造)
②为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
③调用 bean 的初始化的方法(需要进行配置初始化的方法)
④bean 可以使用了(对象获取到了)
⑤当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)
2、bean 的后置处理器,bean 生命周期有七步
@Configuration
@ComponentScan(basePackages = {"com.zichao"})
public class SpringConfig implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在初始化之前执行");
return null;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在初始化之后执行");
return null;
}
}
3、最终生命周期
①执行无参数构造创建bean
②调用set方法设置属性值
③初始化之前执行的方法
④执行初始化方法
⑤初始化之后执行的方法
⑥获取创建的bean实例对象
⑦bean 可以使用了
⑧执行销毁方法
二、AOP
(一)什么是AOP
1、面向切面编程(方面)
利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
2、通俗描述
不通过修改源代码方式,在主干功能里面添加新功能
3、术语
术语 | 含义 |
---|---|
连接点 | 类里那些方法可以被增强,这些方法被称为连接点 |
切入点 | 实际被真正增强的方法,被称为切入点 |
通知 | 实际增强的部分叫做通知 |
切面 | 把通知应用到切入点的过程 |
4、通知的多种类型
前置 后置 环绕 异常 最终
(二)切入点表达式
execution( [权限修饰符] [返回类型] [类全路径] [方法名称] ([参数列表]) )
实例
对 com.zichao.dao.UserDao 类里面的 add 进行增强
execution( * com.zichao.dao.UserDao.add(…))
对 com.zichao.dao.UserDao 类里面的所有的方法进行增强
execution( * comzichao.dao.UserDao.* (…))
对 com.zichao.dao 包里面所有类,类里面所有方法进行增强
execution( * comzichao.dao.*.* (…))
(三)流程
1、创建要增强的类和增强类
public class UserDao {
public void add(){
System.out.println("UserDao add");
}
}
public class UserProxy
{
//前置通知
public void beFore(){
System.out.println("前置通知");
}
}
2、开启注解扫描以及开启生成代理对象
@Configuration
@ComponentScan(basePackages = {"com.zichao"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AopConfig {
}
3、生成两个类的bean对象
@Repository
public class UserDao {
public void add(){
System.out.println("UserDao add");
}
}
@Component
public class UserProxy
{
//前置通知
public void beFore(){
System.out.println("前置通知");
}
}
4、在增强类上面添加注解 @Aspect
@Component
@Aspect
public class UserProxy
{
//前置通知
public void beFore(){
System.out.println("前置通知");
}
}
5、配置不同类型的通知
@Component
@Aspect
public class UserProxy
{
//前置通知
@Before(value = "execution(* com.zichao.Dao.UserDao.add(..))")
public void beFore(){
System.out.println("前置通知");
}
//后置通知,返回通知
@AfterReturning(value = "execution(* com.zichao.Dao.UserDao.add(..))")
public void AfterReturning(){
System.out.println("后置通知");
}
//最终通知
@After(value = "execution(* com.zichao.Dao.UserDao.add(..))")
public void After(){
System.out.println("最终通知");
}
//异常通知
@AfterThrowing(value = "execution(* com.zichao.Dao.UserDao.add(..))")
public void AfterThrowing(){
System.out.println("异常通知");
}
//环绕通知
@Around(value = "execution(* com.zichao.Dao.UserDao.add(..))")
public void Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕之前");
proceedingJoinPoint.proceed();
System.out.println("环绕之后");
}
}
其中环绕通知需要在形参中添加ProceedingJoinPoint,在方法体中调用proceedingJoinPoint.proceed()方法执行被增强类的方法
6、设置增强类优先级
当有多个类同时对一个类进行增强,就需要设置优先级来确定执行顺序
@Component
@Aspect
@Order(1)
public class UserProxy
{}
数子越小,优先级越高
7、提取相同切入点表达式
@Pointcut(value = "execution(* com.zichao.Dao.UserDao.add(..))")
public void execute(){}
//前置通知
@Before(value = "execute()")
public void beFore(){
System.out.println("前置通知");
}
//后置通知,返回通知
@AfterReturning(value = "execute()")
public void AfterReturning(){
System.out.println("后置通知");
}
//最终通知
@After(value = "execute()")
public void After(){
System.out.println("最终通知");
}
//异常通知
@AfterThrowing(value = "execute()")
public void AfterThrowing(){
System.out.println("异常通知");
}
//环绕通知
@Around(value = "execute()")
public void Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕之前");
proceedingJoinPoint.proceed();
System.out.println("环绕之后");
}
8、执行结果
执行发生异常
可以看到,发生异常时执行环绕之前,前置通知,异常通知,最终通知
三、JdbcTemplate
(一)什么是 JdbcTemplate
Spring 框架对 JDBC 进行封装,使用 JdbcTemplate 方便实现对数据库操作
(二)执行步骤(基于完全注解开发)
1、配置配置类
@Configuration
@ComponentScan(basePackages = {"com.zichao"})
public class MySql {
//获取数据库连接
@Bean
public DruidDataSource getDruidDataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
druidDataSource.setUrl("jdbc:mysql:///spring");
druidDataSource.setUsername("root");
druidDataSource.setPassword("7878");
return druidDataSource;
}
//设置JdbcTemplate,把连接注入到JdbcTemplate内
@Bean
public JdbcTemplate getTemplate(DataSource dataSource){
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
}
}
2、编写实体类
public class User {
private Integer id;
private String name;
private String className;
public User() {
}
public User(String name, String className) {
this.id = id;
this.name = name;
this.className = className;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + ''' +
", className='" + className + ''' +
'}';
}
}
3、编写Service和DAO
@Service
public class UserService {
@Autowired
UserDao userDao;
//添加数据
public void addUser(User user){
userDao.addUser(user);
}
}
@Repository
public class UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public void addUser(User user){
String sql = "insert into user(name,className) values(?,?)";
jdbcTemplate.update(sql,user.getName(),user.getClassName());
}
}
其中Service中要注入Dao类,Dao中要注入JdbcTemplate,进行插入数据时,执行JdbcTemplate的update方法,方法共有两个形参,一个是sql语句,一个是填写占位符
4、编写测试类
public class TestUser {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MySql.class);
UserService userService = applicationContext.getBean("userService", UserService.class);
userService.addUser(new User("songwu","android"));
}
}
和IOC和AOP操作一致,都是加载配置类获取bean,再执行方法
5、修改和删除
修改和删除执行的都是JdbcTemplate的update方法,就是sql语句和占位符不同。
//修改
@Autowired
private JdbcTemplate jdbcTemplate;
public void upDataUser(User user){
String sql = "updata user set name = ? where id = ?";
jdbcTemplate.update(sql,user.getName(),user.getId());
}
//删除
@Autowired
private JdbcTemplate jdbcTemplate;
public void deleteUser(User user){
String sql = "delete from user where id = ?";
jdbcTemplate.update(sql,user.getId());
}
6、查询返回某个值
查询返回某个值使用的是JdbcTemplate的queryForObject方法,一共有两个参数,一个是sql语句,一个是返回值类型。
//查询表总数
@Autowired
private JdbcTemplate jdbcTemplate;
public int userCount(){
String sql = "select count(*) from user";
Integer integer = jdbcTemplate.queryForObject(sql, Integer.class);
return integer;
}
7、查询返回对象
查询返回对象使用的也是JdbcTemplate的queryForObject方法,但是一共有三个参数,一个是sql语句,一个是RowMapper 是接口,使用这个接口里面实现类完成数据封装,第三个是占位符。
//根据id查询信息
@Autowired
private JdbcTemplate jdbcTemplate;
public User userSelect(User user){
String sql = "select * from user where id = ?";
User userSelect = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), user.getId());
return userSelect;
}
8、查询返回集合
查询返回对象集合使用的也是JdbcTemplate的query方法,也有三个参数,一个是sql语句,一个是RowMapper 是接口,使用这个接口里面实现类完成数据封装,第三个是占位符。
//查询所有人的信息
@Autowired
private JdbcTemplate jdbcTemplate;
public List<User> userSelect(User user){
String sql = "select * from user ";
List<User> users = jdbcTemplate.query(sql, new BeanPropertyRowMapper<User>(User.class));
return users;
}
9、批量操作
批量操作使用JdbcTemplate的batchUpdate方法,该方法有两个参数,第一个参数为sql语句,第二个参数为:List 集合,为要操作的多条数据
//添加多条数据
@Autowired
private JdbcTemplate jdbcTemplate;
public void BatchUser(List lists){
String sql = "insert into user(name,className) values(?,?)";
jdbcTemplate.batchUpdate(sql,lists);
}
//测试
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MySql.class);
UserService userService = applicationContext.getBean("userService", UserService.class);
List<Object[]> list = new ArrayList<>();
Object[] o1 = {"zhansan", "android"};
Object[] o2 = {"lisi", "java"};
list.add(o1);
list.add(o2);
userService.BatchUser(list);
}
修改与删除和添加一样,就是sql语句和传入的数组不同。
四、Spring中队事务的管理
(一)什么事务
① 事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个失败所有操作都失败
② 典型场景:银行转账
(二)事务四个特性(ACID)
① 原子性
② 一致性
③ 隔离性
④ 持久性
(三)事务操作过程
① 在进行dao操作时,首先开启事务
② 进行业务操作
③ 没有发生异常,提交事务
④ 出现异常,回滚事务
(四)Spring 事务管理介绍
① 事务添加到Service 层
② 在 Spring 进行事务管理操作,特指进行声明式事务管理(注解方式)
③ 在 Spring 进行声明式事务管理,底层使用 AOP 原理
④ Spring 事务管理 API:提供一个接口,代表事务管理器,这个接口针对不同的框架提供不同的实现类,在java中使用DataSourceTransactionManager
(五)具体操作
1、编写配置类(在上一个模块基础上)
@Configuration
@ComponentScan(basePackages = {"com.zichao"})
@EnableTransactionManagement //开启事务
public class MySql {
//获取数据库连接
@Bean
public DruidDataSource getDruidDataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
druidDataSource.setUrl("jdbc:mysql:///spring");
druidDataSource.setUsername("root");
druidDataSource.setPassword("7878");
return druidDataSource;
}
//设置JdbcTemplate,把连接注入到JdbcTemplate内
@Bean
public JdbcTemplate getTemplate(DataSource dataSource){
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
}
//创建事务管理器
@Bean
public DataSourceTransactionManager
getDataSourceTransactionManager(DataSource dataSource) {
DataSourceTransactionManager transactionManager = new
DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
}
2、在 service 类上面(或者 service 类里面方法上面)添加事务注解
① 如果把这个注解添加类上面,这个类里面所有的方法都添加事务
② 如果把这个注解添加方法上面,为这个方法添加事务
③ 该注解有多个值
3、对一些重要参数进行解释
(1)propagation:事务传播行为
事务的传播行为可以由传播属性指定,一共有7种
如:
@Transactional(propagation = Propagation.REQUIRED)
(2)ioslation:事务隔离级别
事务有特性成为隔离性,多事务操作之间不会产生影响。不考虑隔离性产生很多问题,如脏读、不可重复读、虚(幻)读。
① 脏读:一个未提交事务读取到另一个未提交事务的数据
② 不可重复读:一个未提交事务读取到另一提交事务修改数据
③ 一个未提交事务读取到另一提交事务添加数据
解决:通过设置事务隔离级别,解决问题
如:
@Transactional(
propagation = Propagation.REQUIRED,
isolation = Isolation.REPEATABLE_READ
)
(3)timeout:超时时间
事务需要在一定时间内进行提交,如果不提交进行回滚
默认值是 -1 ,设置时间以秒单位进行计算
(4)readOnly:是否只读
读:查询操作,写:添加修改删除操作
readOnly 默认值 false,表示可以查询,可以添加修改删除操作
设置 readOnly 值是 true,设置成 true 之后,只能查询
(5)rollbackFor:回滚
设置出现哪些异常进行事务回滚
(6)noRollbackFor:不回滚
设置出现哪些异常不进行事务回滚
五、Spring5 框架新功能
(一)代码整理
整个 Spring5 框架的代码基于 Java8,运行时兼容 JDK9,许多不建议使用的类和方法在代码库中删除
(二)Spring 5.0 框架自带了通用的日志封装
Spring5 已经移除 Log4jConfigListener,官方建议使用 Log4j2
(三)Spring5 框架核心容器支持@Nullable 注解
@Nullable 注解可以使用在方法上面,属性上面,参数上面,表示方法返回可以为空,属性值可以为空,参数值可以为空
(四)Spring5 核心容器支持函数式风格GenericApplicationContext
(五)Spring5 支持整合 JUnit5
(六)SpringWebflux
最后
以上就是英勇糖豆为你收集整理的(zichao)我的Spring5学习笔记(仅作简单整理,未深入探究)一、IOC容器二、AOP三、JdbcTemplate四、Spring中队事务的管理五、Spring5 框架新功能的全部内容,希望文章能够帮你解决(zichao)我的Spring5学习笔记(仅作简单整理,未深入探究)一、IOC容器二、AOP三、JdbcTemplate四、Spring中队事务的管理五、Spring5 框架新功能所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复