spring学习笔记

如何学习spring

spring理论(能听懂技术介绍,并且可以对其他人说出去)

spring基础(IoC、DI、AOP)---很重要(spring boot、spring cloud 、spring data)

spring源码(重点是帮助深入理解spring应用)

spring应用(JDBC支持、事务支持、和mybatis整合)

可以解决spring框架中暴露出的问题(调bug)

交接(spring信息同步)

Spring介绍

  • 我们现在学习的spring,spring framework(包含了20多个模块)其中里面有web mvc模块(springmvc)

  • springboot 、springcloud 与 spring framework不存在包含关系。

  • spring提供了一站式企业应用解决方案(企业开发的一条龙服务、邮件、消息服务、开发框架)。

  • spring容器其实指的就是IoC容器,Ioc容器指的就是BeanFactory工厂(DefaultListableBeanFactory)。BeanFactory有一个子接口叫ApplicationContext(应用上下文接口)。

  • 我们需要了解spring容器的初始化过程(BeanFactory是如何管理Bean的实例的,需要源码专题去解决)

  • IoC:控制反转,创建Bean对象的角色发送了反转,由程序员创建,反转为Spring容器创建。

  • DI:基于IoC的,在Bean对象创建的过程中,需要注入属性(基本属性、对象属性、集合数组属性)

  • AOP:

    • 面向切面的编程,它只是一种aop联盟提出来的编程思想,根据这种编程思想,有很多的实现:AspectJ、Spring AOP、Spring 整合了AspectJ。

    • AOP的主要作用:横向抽取重复代码,实现代码的重用(事务、日志监控等)、AOP是为了弥补OOP的一些不足。

      • 纵向抽取(继承)
      spring学习笔记_第1张图片
      1543843592214.png
      • 横向抽取(AOP)
    spring学习笔记_第2张图片
    1543843558302.png

Spring 入口

所谓的spring入口,指的就是如何启动spring容器。

  • 基于XML

    • java应用

      ApplicationContext ctx = new ClasspathXmlApplicationContext("spring.xml");
      
    • web应用

      web.xml

      
          contextConfigLocation
          classpath:spring.xml
      
      
          
              ContextLoaderListener
          
      
      

      ContextLoaderListener监听器中,会去调用getWebApplicationContext()—>AbstractApplicationContext()

  • 基于注解

    • java应用

      ApplicationContext ctx = new AnnotationConfigApplicationContext(@Configuration配置类);
      
    • web应用

      web.xml

      
          contextConfigLocation
          @Configuration配置类
      
      
          
              ContextLoaderListener
          
      
      

      ContextLoaderListener监听器中,会去调用getWebApplicationContext()—>AbstractApplicationContext()

      getWebApplicationContext得到的默认实现类AnnotationConfigWebApplicationContext

IoC和DI的三种实现方式

基于XML

  • java代码---面向接口开发(正常编写)

  • spring xml配置文件

    • IoC---bean标签 ,表示该bean交给spring容器管理
      • id
      • init-method 初始化方法(源码分析部分,看到该属性啥时候执行)
      • destroy-method 它的值就是一个方法名称
        • 数据库连接池配置的时候,一定要配置它,具体配置看bean的class类中定义的销毁方法是什么
    • DI —bean标签的property子标签和constractor�-arg子标签
      • ref
      • value

基于注解和XML混合

  • java代码

    • IoC注解:@Component、@Controller、@Service、@Repository
    • DI注解:第一步:在IoC容器中查找指定的依赖第二步:属性注入
      • @Value(注入基本类型和String类型)
        • ${xxx}
        • context:property-placeholder:第一个去加载指定的properties文件、第二个就是将读取到的key/value数据,去替换spring上下文中出现的属性占位符 ${xxx}
      • @Autowired(byType---class类型)---spring提供的注解。
        • byName—需要配合@Qualifier注解
      • @Resource(默认先byName[bean的id或者name])、再byType),建议使用。它是由java提供的注解。
      • @Inject(默认是byType)
        • byName — @Name
  • spring xml配置

    • dataSource这种第三方的Bean对应的Bean标签

    • context:component-scan:

      • 开启@Autowired等几个注解的功能(BeanFactoryPostProcessor)。
        • 专门开启@Autowired注解的配置 context:annotation-driven
      • 扫描该应用上下文中指定包下面的IoC注解,将这些扫描到的Bean,交给spring容器进行管理。

基于纯注解

  • 零配置:是说的没有spring xml配置文件了,有没有可能包含mybatis(映射文件)
  • java代码:
    • @Configuration:替代XML配置文件
    • @ComponentScan:替代context:component-scan标签
    • @Bean:替代bean标签的。
    • @ProperySource:主要是替代context:property-placeholder标签的
    • @Import:替代import标签,可以将另一个@Configuration类引入到当前配置类中

基于XML和注解方式的优缺点

注解的优势:

​ 配置简单,维护方便(我们找到类,就相当于找到了对应的配置)。

l XML 的优势:

​ 修改时,不用改源码。不涉及重新编译和部署。

AOP的三种实现方式

AOP原理

AOP的作用:在不修改代码的情况下,对功能进行增强(开闭原则)

预编译方式和运行时代理方式

  • AspectJ是采取的预编译方式(静态织入)
  • Spring AOP是采取的运行时代理方式(动态代理)
    • JDK动态代理---基于接口
    • CGLib动态代理---基于继承(任何一个非final类都可以被继承)

AOP术语

  • 切入点:待增强的方法
  • 通知(增强):日志、事务等功能
  • 织入
  • 切面:切入点和通知的组合
  • 目标对象:表现层、业务层、持久层的相关代码。目标对象无须被修改。
  • 代理:最终生成的对象。

一句话概括AOP就是:在【目标对象】中定位【切入点】,【织入】对应的【通知】,就变成了【代理对象】

基于XML(spring整合aspectJ)

  • 目标对象(Service实现类)

  • 编写通知类(单独的类,无须继承任何类和实现任何接口)

  • spring配置文件

    
    
    
      
         
        
        
        
        
            
          
          
        
    
    
    • 通知类型(五种)

      • * 通知类型(五种):前置通知、后置通知、最终通知、环绕通知、异常抛出通知。

        * 前置通知:

        ​ * 执行时机:目标对象方法之前执行通知

        ​ * 配置文件:

        ​ * 应用场景:方法开始时可以进行校验

        * 后置通知:

        ​ * 执行时机:目标对象方法之后执行通知,有异常则不执行了

        ​ * 配置文件:

        ​ * 应用场景:可以修改方法的返回值

        * 最终通知:

        ​ * 执行时机:目标对象方法之后执行通知,有没有异常都会执行

        ​ * 配置文件:

        ​ * 应用场景:例如像释放资源

        * 环绕通知:

        ​ * 执行时机:目标对象方法之前和之后都会执行。

        ​ * 配置文件:

        ​ * 应用场景:事务、统计代码执行时机

        * 异常抛出通知:

        ​ * 执行时机:在抛出异常后通知

        ​ * 配置文件:

        ​ * 应用场景:包装异常

    • 切入点表达式

      execution(返回值 包名.类名.方法名(参数类型))

基于注解和XML混合(spring整合aspectJ)

  • 目标对象(Service实现类)

  • 编写切面类

    • 类上必须加上@Aspect(标记该类是一个AOP 切面类)、@Component(标记该类可以被组件扫描器扫描到spring容器中)

    • 方法上需要加上@Before、@AfterReturning等五个注解,分别对应五种通知类型。

    • 可以在一些方法上加上@PointCut注解(为了去声明一个切入点表达式),该方法可以被@Before、@AfterReturning注解使用。

    • 示例:

      @Component("myAspect")
      @Aspect
      public class MyAspect {
          
          private static final String pcut="execution(* *..*.*ServiceImpl.*(..))";
          
          @Before(value="MyAspect.fn()")
          public void before() {
              System.out.println("这是注解方式的前置通知");
          }
          
          @After(value="execution(* *..*.*ServiceImpl.*(..))")
          public void after() {
              System.out.println("这是注解方式的最终通知");
          }
          
          @AfterReturning(pcut)
          public void after() {
              System.out.println("这是注解方式的后置通知");
          }
          
          @Pointcut("execution(* *..*.*ServiceImpl.*(..))")
          public void fn() {}
      }
      
      
  • spring配置文件

      
      
      
      
      
    

基于纯注解(spring整合aspectJ)

以下代码,主要替换的就是spring配置文件

@Configuration
@ComponentScan("com.kkb.spring.aop")
@EnableAspectJAutoProxy
public class SpringConfiguration{
    
}

Spring整合Junit

为Springmvc的MockMVC做铺垫

  • junit是专门实现单元测试的

    单元测试,主要测试的是业务逻辑。

  • 编写spring单元测试代码遇到的问题

    ApplicationContext ctx = 
                  new ClassPathXmlApplicationContext("spring.xml");
    UserService service1 = context.getBean(UserService.class);
    
    

    以上代码每一个单元测试代码都要编写,但是它又和我们要测试的业务逻辑,没有关系。

  • 解决思路:Junit是通过@RunWith注解,让我们制定一个自定义的运行器(spring已经实现)去运行单元测试代码。

  • 示例

    @RunWith(SpringJunit4ClassRunner.class)
    //加载XML配置文件的写法
    @ContextConfiguration(locations="classpath:spring.xml")
    //加载Java配置类的写法
    //@ContextConfiguration(classes=SpringConfiguration.class)
    public class TestSpring{
        
        @Resource
        private UserService service;
        
        @Test
        public void testAop(){
            service.saveUser();
        } 
    }
    

Spring应用之JDBC实现

模板模式:将模板化的代码,抽象为一个抽象类,然后定义一个或多个abstract方法待子类去实现。

持久层的相关框架(封装了JDBC):

  • mybatis:和spring整合需要第三方中间整合包(mybatis)
  • ibatis
  • hibernate
  • spring JDBC:本来就是spring的模块,无需和spring整合。
    • JdbcTemplate:模板类,主要就是通过该类实现增删改查。
  • DBUtils

示例代码:

    @Test
    public void run1(){
        // 创建连接池,先使用Spring框架内置的连接池
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql:///spring");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        // 创建模板类
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        // 完成数据的添加
        jdbcTemplate.update("insert into account values (null,?,?)", "测试",10000);
    }

  • JdbcDaoSupport
    • 封装了JdbcTemplate
    • 继承了该类,则不需要在spring配置文件中,注入JdbcTemplate对象了。

spring应用之事务支持

​ (看源码--分析事务是如何实现的并且深刻理解AOP的功能)

事务

  • Spring事务:只是做了事务管理。

    Spring并不直接管理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现。 Spring事务管理器的接口是PlatformTransactionManager,通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。

spring学习笔记_第3张图片
1544017570886.png
  • jdbc事务

  • MySQL事务:讲解MySQL的时候会去详细介绍(redo日志、undo日志)

    总结:事务最终都是由数据库本身去实现的。

事务的四大特性

ACID的理解:

  • A:原子性

    操作不可分割,要么都成功、要么都失败。

  • C:一致性

    账户A(600元)和账户B(400元)总共有1000块钱。

    账户A(600元)给账户B(400元)转账200元,最终的结果不管是成功还是失败,A和B的总额还是1000元。

  • I:隔离性(由锁机制实现的。会引起并发访问问题)

    为了保证A事务和B事务之间操作是互不影响。

  • D:持久性:将结果保存到数据库文件中。

事务并发问题

隔离性不好会引起事务并发问题。

  • 更新丢失
  • 脏读:A事务读到了B事务未提交的数据。
  • 不可重复读:A事务两次读取同一行记录,显示的结果不一致。原因是两次读取期间,B事务对该记录进行了更新操作。
  • 幻读:A事务两次读取同一张表,显示的结果条数不一致。原因是两次读取期间,B事务对该表进行了增加和删除操作。

SQL92标准提出了四种隔离级别:

① Read uncommitted (读未提交):最低级别,任何情况都无法保证。

② Read committed (读已提交):可避免脏读的发生。

③ Repeatable read (可重复读):可避免脏读、不可重复读的发生。(注意事项:MySQL在该级别的时候,就可以将幻读给解决掉

④ Serializable (串行化):可避免脏读、不可重复读、幻读的发生。

MySQL数据库的默认隔离级别是Repeatable Read

注意事项:

隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。

spring两种事务实现

spring有两种事务实现方式:编程式事务(不推荐使用)、声明式事务。

spring声明式事务

XML方式

  • spring配置文件

    
    
    
      
    
    
      
            
              
            
          
              
              
              
              
          
      
    
    
    
    
    
          
          
          
      
    

混合方式

由同学们自己去实现

纯注解方式

由同学们自己去实现

Spring和Mybatis整合

需求

查询account表的记录

整合思路

需要整合的,就是项目中的对象(这些对象都要被spring管理)

  • 分析有哪些对象需要被spring管理(确定是XML方式还是纯注解方式来管理)

    • 业务层
      • 实现类(多个)
      • 事务相关的对象
        • 事务管理器
        • 通知类
        • 切面类
    • 持久层(mybatis)
      • 数据源(一个)
      • SqlSessionFactory对象(一个)
      • Mapper代理对象(多个)
  • 配置spring文件(分模块配置思想---便于维护)

    • 持久层---一个spring配置文件

      
      
      
      
          
      
      
      
      
          
      
      
    • 业务层

      • 业务类---一个spring配置文件
      • 事务类---一个spring配置文件
    • 将所有spring配置文件整合到一起(方式有多种,具体有哪些??????

  • 问题:

    • 不知道加哪些依赖?只需要添加最基本的依赖,保证程序不报错即可。

源码专题

你可能感兴趣的:(spring学习笔记)