Spring三天学习总结

Spring总结

1.什么是Spring

  • Spring是一个Java框架,用来操作JavaBean。

  • 是一个开源框架。

2.Spring的作用

  1. 简化开发

  2. 降低程序耦合性

  3. 整合市面上主流框架,

  • SpringMvc:Web框架,是一个基于MVC设计模式的轻量级Web开发框架。本质相当于是Servlet。和Spring框架无缝继承,性能好,是市面上主流的Web框架。

  • Mybatis:持久层(Dao层)框架,用来操作数据库。本质上是JDBC,隐藏了JDBC的繁琐操作。

  • SpringBoot:基于Spring4.0设计,简化开发,内置tomcat,Spring+SpringMVC+Mybatis总和。

3.为什么要学Spring

JavaWeb项目操作复杂,不易维护。Spring能帮助我们管理JavaWeb项目。

4.Spring核心技术

IOC和DI:

我们通常会在不同的类new相同的对象,操作复杂,繁琐。不易维护,如果一个对象改变了,代码都需要改变。

  • IOC(控制反转):

将JavaBean的创建与销毁交给Spring容器统一管理。

IOC容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在IOC容器中统称为Bean

能够提高效率,建议单例对象放在容器中,多例对象自己new。

  • DI注入:

容器中Bean可能会存在关联关系,如果我们要使用就需要关联起来。给一个Bean对象注入另一个Bean对象的这个过程就叫做DI注入。

AOP:

  • 面向切面编程,一种编程范式,指导开发者如何组织程序结构

    • 与面向对象一个概念。

  • Spring理念:无入侵式|无侵入式

  • 在不改变方法本身的情况下,进行方法增强。

  1. 连接点:方法。

  2. 切入点:需要增强的方法。

  3. 通知:增强的内容。

  4. 通知类:统一管理增强内容的类。

  5. 切面:将通知放入需要增强的方法的的地方。

核心概念:

  • 目标对象(Target):被代理的对象,也叫原始对象,该对象中的方法没有任何功能增强。

  • 代理对象(Proxy):代理后生成的对象,由Spring帮我们创建代理对象。类似于Mybatis中的getMapper(BookDao.class);

3.使用

1.IOC:

  1. 开启注解扫描:

配置文件开启:

  <!--扫描com.itheima包及其子包下的类中注解-->
     <context:component-scan base-package="com.itheima"/>

注解开启:

 @Configuration
 @ComponentScan("com.itheima")
 public calss SprinConig{}

容器启动的时候,加载此包下面的所有类,将加了注解的类添加到容器中。

2.定义Bean:

添加内部Bean:

Spring提供@Component注解的三个衍生注解

  • @Controller:用于表现层bean定义

  • @Service:用于业务层bean定义

  • @Repository:用于数据层bean定义

容器启动的时候会扫描指定包下面,如果加上如上注解,就会自动创建Bean对象注入Spring容器中,管理Bean的初始化与销毁。

配置第三方Bean:

@Bean 表示当前方法的返回值是一个bean对象,添加到IOC容器中。

使用场景:datasource注入,SqlSessionFactory注入...

 public class JdbcConfig {
     //@Bean:表示当前方法的返回值是一个bean对象,添加到IOC容器中
     @Bean
     public DataSource dataSource(){
         DruidDataSource ds = new DruidDataSource();
         ds.setDriverClassName("com.mysql.jdbc.Driver");
         ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
         ds.setUsername("root");
         ds.setPassword("root");
         return ds;
     }
 }

3.设置依赖注入:

@Autowired:默认按照类型从容器装配。如果容器中同类的Bean有多个,那么默认按照变量名与Bean的名称匹配。

 @Autowired
 private BookDao bookDao1;

@Qualifier:从容器中取的时候,按照指定名称取。必须配合@Autowired使用。

 @Qualifier("bookDao1")
 @Autowired
 private BookDao bookDao;

@Value:可以对简单类型的注入,可以自己定义,也可从配置文件中读取。

需要在SrpingConfig添加@PropertySource注解,指定从那个配置文件中读取。可以指定多个,建议添加classpath

 @Configuration
 @PropertySource({"classpath:jdbc.properties"})
 public calss SprinConig{}

从配置文件中读取name属性的值赋给变量name。

 //@Value:注入简单类型(无需提供set方法)
     @Value("${name}")
     private String name;

作用范围

@Scope:配置Bean的作用范围,单例或者多例。默认是单例模式。

 @Scope("singleton")
 public class BookDaoImpl implements BookDao {
 }

生命周期

@PostConstruct:修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行。

执行顺序:

 Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)

@PreDestroy:在服务器卸载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet的destroy()方法。被@PreDestroy修饰的方法会在destroy()方法之后运行,在Servlet被彻底卸载之前。

注意:@PostConstruct和@PreDestroy注解是jdk中提供的注解,从jdk9开始,jdk中的javax.annotation包被移除了,也就是说这两个注解就用不了了,可以额外导入一下依赖解决这个问题。

 <dependency>
   <groupId>javax.annotation</groupId>
   <artifactId>javax.annotation-api</artifactId>
   <version>1.3.2</version>
 </dependency>

4.需要配置SpringConfig配置文件,加载Bean对象到容器中。

@Configuration指定当前类是个配置类

@Import导入外部Bean的配置,可以导入多个。

 @Configuration
 //@Import:导入配置信息
 @Import({JdbcConfig.class})
 public calss SprinConig{
     
 }

2.AOP

工作流程:

  1. Spring容器启动

  2. 读取所有切面配置中的切入点

  3. 初始化bean,判定bean对应的类中的方法是否匹配到任意切入点

    • 匹配失败,创建原始对象

    • 匹配成功,创建原始对象(目标对象)的代理对象

  4. 获取bean执行方法

    • 获取的bean是原始对象时,调用方法并执行,完成操作

    • 获取的bean是代理对象时,根据代理对象的运行模式运行原始方法与增强的内容,完成操作

1.切入点表达式,用于指定要增强的方法的路径。

  • 切入点表达式标准格式:动作关键字(访问修饰符 返回值 包名.类/接口名.方法名(参数)异常名)

    • execution(* com.itheima.service.Service.(..))

  • 切入点表达式描述通配符:

    • 作用:用于快速描述,范围描述

    • *:匹配任意符号(常用)

    • .. :匹配多个连续的任意符号(常用)

    • +:匹配子类类型

  • 切入点表达式书写技巧

    1.按标准规范开发 2.查询操作的返回值建议使用*匹配 3.减少使用..的形式描述包 4.对接口进行描述,使用*表示模块名,例如UserService的匹配描述为*Service 5.方法名书写保留动词,例如get,使用*表示名词,例如getById匹配描述为getBy* 6.参数根据实际情况灵活调整

下面表达的是:在cn.hmc.testaop包下面的TestAop类中返回值为void,方法名为update没有入参的方法。

反过来阅读:倒数第一个是方法名,倒数第二个是类名,除了第一个剩下的都是包名

  //设置切入点
     @Pointcut("execution(void cn.hmc.testaop.TestAop.update()))")
     private void pt(){}

简化版本:

匹配cn.hmc.testaop包下面任意以AOP结尾的类,返回值任意,方法名任意,方法参数任意。

 @Pointcut("execution(* cn.hmc.testaop.*Aop.*(..))")
     private void test(){}

极度简化:

匹配当前项目下任意包,任意类,任意返回值,任意方法。

 @Pointcut("execution(* ...*.*(..))")
     private void test2(){}

2.AOP通知

  • AOP通知描述了抽取的共性功能,根据共性功能抽取的位置不同,最终运行代码时要将其加入到合理的位置

  • AOP通知共分为5种类型

    • 前置通知:在切入点方法执行之前执行

    • 后置通知:在切入点方法执行之后执行,无论切入点方法内部是否出现异常,后置通知都会执行。

    • 环绕通知(重点):手动调用切入点方法并对其进行增强的通知方式。

    • 返回后通知(了解):在切入点方法执行之后执行,如果切入点方法内部出现异常将不会执行。

    • 抛出异常后通知(了解):在切入点方法执行之后执行,只有当切入点方法内部出现异常之后才执行。

1.前置通知:在切入点方法执行之前执行

 @Before("pt()")
 public void before() {
     System.out.println("before advice ...");
 }

2.后置通知:在切入点方法执行之后执行

 @After("pt()")
 public void after() {
     System.out.println("after advice ...");
 }

3.返回后通知:在切入点方法正常执行完毕后运行

 @AfterReturning("pt()")
 public void afterReturning() {
     System.out.println("afterReturning advice ...");
 }

4.抛出异常后通知:在切入点方法运行抛出异常后执行

 @AfterThrowing("pt()")
 public void afterThrowing() {
     System.out.println("afterThrowing advice ...");
 }

5.环绕通知:在切入点方法前后运行。

 @Around("pt()")
 public Object around(ProceedingJoinPoint pjp) throws Throwable {
     System.out.println("around before advice ...");
     Object ret = pjp.proceed();
     System.out.println("around after advice ...");
     return ret;
 }

ProceedingJoinPoint常用方法:

 # 返回目标对象,即被代理的对象
 Object getTarget();
 ​
 # 返回切入点的参数
 Object[] getArgs();
 ​
 # 返回切入点的Signature
 Signature getSignature();
 ​
 # 返回切入的类型,比如method-call,field-get等等,感觉不重要 
  String getKind();

JointPointProceedingJoinPoint的父类 , 在其他通知中可以获取到 . ProceedingJoinPoint只能在环绕通知中获取.

环绕通知注意事项

  1. 环绕通知方法形参必须是ProceedingJoinPoint,表示正在执行的连接点,使用该对象的proceed()方法表示对原始对象方法进行调用,返回值为原始对象方法的返回值。

  2. 环绕通知方法的返回值建议写成Object类型,用于将原始对象方法的返回值进行返回,哪里使用代理对象就返回到哪里

开启AOP注解支持

 @Configuration//声明当前类是一个Spring配置类
 @ComponentScan("com.itheima")//扫描指定包下面的类是否能够添加进容器.根据注解判断
 @PropertySource("classpath:jdbc.properties")//@Value读取的配置文件
 @Import({JdbcConfig.class,MybatisConfig.class})//外部bean的定义类
 @EnableAspectJAutoProxy //开启AOP注解功能
 public class SpringConfig {
 }

3.Spring事务管理

事务是对数据库的一组操作,要么同时成功要么同时失败。

  • 原子性:事务是不可分割的,要么同时成功,要么同时失败

  • 一致性:一致性事务操作前后数据总量不变

  • 隔离性:事物之间互补影响

  • 持久性:事务提交或回滚数据将会永久存在磁盘中

不考虑隔离性产生的问题:

  • 脏读:一个事务读取到另一个事务未提交的数据

  • 不可重复读:一个事务开启后多次读取数据不一致

  • 幻读:一个事务进行整表操作后,结果与预期不一致

解决:

隔离级别:

  • 串行化:事务一个一个排队

  • 可重复读:能解决不可重复度以及脏读问题 mysql默认

  • 读已提交:能解决脏读问题 oracle默认

  • 读未提交:不能解决任何问题

Spring事务作用:

事务作用:在数据层保障一系列的数据库操作同成功同失败

Spring事务作用:在数据层或业务层保障一系列的数据库操作同成功同失败

例子: 转账问题:

A到银行给B转账,首先银行会将A的钱扣除,然后给B的钱增加.

正常执行没有问题,如果在扣除A的钱之后出现了异常,业务就会失败,A扣了钱,B没有加钱,不符合业务需求.

这个时候需要给执行这个流程的业务添加一个事务,保证在出现异常之后回滚到执行业务之前的状态.

开启事务注解支持:

 @Configuration
 @ComponentScan("com.itheima")
 @PropertySource("classpath:jdbc.properties")
 @Import({JdbcConfig.class,MybatisConfig.class})
 //开启注解式事务驱动
 @EnableTransactionManagement
 public class SpringConfig {
 }

在处理转账的接口上添加事务注解:

 public interface AccountService {
     //配置当前接口方法具有事务
     @Transactional
     public void transfer(String out,String in ,Double money) ;
 }

此方法运行的时候就会生成一个事务包裹里面的业务,出错自动回滚.

有时我们需要捕获一些错误信息,又需要进行事务回滚,这时我们就需要用到Spring提供的事务切面支持类TransactionAspectSupport。

         int i = userDao.saveUser();
         //如果用户添加失败,我们就不添加学生
         if(i<1){
                   //手动强制回滚事务,这里一定要第一时间处理
 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 
             throw new TestEception("添加用户失败!");
         }
         i = studentDao.saveStudent();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值