Spring学习笔记(篇二)

代码地址: https://github.com/Zhuyaqiang/spring-study

目录

  • 10 代理模式
    • 10.1 静态代理
    • 10.2 加深理解
    • 10.3 动态代理
      • 动态代理的好处:
  • 11 AOP
    • 11.1 AOP在Spring中的作用
    • 11.2 使用Spring实现AOP
      • 11.2.1方式一: 使用Spring的API接口
      • 11.2.2 方式二: 使用自定义类实现AOP[主要是切面定义]
      • 方式三: 使用注解实现
  • 12 整合Mybatis
    • 12.1 mybatis
    • 12.2 Mybatis-Spring
  • 13 声明式事务
    • 1 事务
    • 2 spring中的事务管理

10 代理模式

代理模式是SpringAOP的底层

代理模式的分类

  • 静态代理
  • 动态代理

10.1 静态代理

对应springboot-08-proxy

角色分析:

  • 抽象角色: 一般会使用接口或者抽象类来解决
  • 真实角色: 被代理的角色
  • 代理角色: 代理这是角色, 代理真实角色后, 我们一般会做一些附属操作
  • 客户: 访问对象的人

代码步骤:

  1. 接口
  2. 真实角色
  3. 代理角色
  4. 客户端访问代理角色

代理模式的好处:

  • 可以使真实角色的操作更加纯粹, 不用去关注一些公共的业务
  • 公共业务交给代理角色, 实现了业务的分工
  • 公共你业务发生扩展的时候, 方便集中管理

缺点:

  • 一个真实角色就会产生一个代理角色, 代码量会翻倍, 开发效率会变低

10.2 加深理解

对应spring-08-demo02

10.3 动态代理

  • 动态代理和静态代理角色一样
  • 动态代理的代理类是动态生成的, 不是直接写好的
  • 动态代理分为两大类: 基于接口动态代理, 基于类的动态代理
    • 基于接口: JDK动态代理
    • 基于类: cblib
    • java字节码实现: javassist

了解两个类: Proxy: 代理, InvocationHandler: 调用处理程序

动态代理的好处:

  • 可以使真实角色的操作更加纯粹, 不用去关注一些公共的业务
  • 公共业务交给代理角色, 实现了业务的分工
  • 公共你业务发生扩展的时候, 方便集中管理
  • 一个动态代理类代理的是一个接口, 一般就是对应的一类业务
  • 一个动态代理类可以代理多个类, 只要是实现了同一个接口即可

11 AOP

11.1 AOP在Spring中的作用

提供声明式事务, 允许用户自定义切面

  • 横切关注点: 跨越应用程序多个模块的方法或功能. 即与业务逻辑无关的但是需要关注的部分, 如日志, 安全, 缓存, 事务等等------以log为例
  • 切面: 横切关注点被模块化的特殊对象, 即一个类------log类
  • 通知: 切面必须完成的工作, 即类中的方法------log类中的方法
  • 目标: 被通知对象
  • 代理: 向目标对象应用通知之后创建的对象------代理类
  • 切入点: 切面通知执行的"地点"的定义
  • 连接点: 与切入点匹配的执行点

11.2 使用Spring实现AOP

重点: 导入依赖


<dependency>
    <groupId>org.aspectjgroupId>
    <artifactId>aspectjweaverartifactId>
    <version>1.9.5version>
dependency>

11.2.1方式一: 使用Spring的API接口

定义log类, 实现AfterReturningAdvicec/MethodBeforeAdvice等接口, 再在配置文件中配置

public class AfterLog implements AfterReturningAdvice {
    // returnValue: 返回值
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("执行了" + method.getName() + ", 返回结果为: " + returnValue);
    }
}


<aop:config>
    
    <aop:pointcut id="pointcut" expression="execution(* com.zyq.service.UserServiceImpl.* (..))">aop:pointcut>

    
    <aop:advisor advice-ref="log" pointcut-ref="pointcut">aop:advisor>
    <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut">aop:advisor>
aop:config>

11.2.2 方式二: 使用自定义类实现AOP[主要是切面定义]

public class DiyPointCut {
    public void before() {
        System.out.println("========方法执行前==========");
    }
    public void after() {
        System.out.println("========方法执行后==========");
    }
}
<bean id="diy" class="com.zyq.diy.DiyPointCut">bean>
<aop:config>
    
    <aop:aspect ref="diy">
        
        <aop:pointcut id="point" expression="execution(* com.zyq.service.UserServiceImpl.*(..))"/>
        
        <aop:before method="before" pointcut-ref="point">aop:before>
        <aop:after method="after" pointcut-ref="point">aop:after>
    aop:aspect>
aop:config>

方式三: 使用注解实现

@Aspect // 标注这个类是一个切面
public class AnnotationPointCut {
    @Before("execution(* com.zyq.service.UserServiceImpl.*(..))")
    public void before() {
        System.out.println("=====方法执行前=======");
    }

    @After("execution(* com.zyq.service.UserServiceImpl.*(..))")
    public void after() {
        System.out.println("=====方法执行后=======");
    }

    // 在环绕增强中, 可以给定一个参数, 代表要获处理切入的点
    @Around("execution(* com.zyq.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕前");
        // 执行方法
        Object proceed = joinPoint.proceed();
        System.out.println("环绕后");
    }
}

    <bean id="annocationPointCut" class="com.zyq.diy.AnnotationPointCut">bean>

    <aop:aspectj-autoproxy proxy-target-class="false">aop:aspectj-autoproxy>

12 整合Mybatis

步骤:

  1. 导入jar包
    • junit
    • mybatis
    • mysql数据库
    • spring相关
    • aop织入
    • mybatis-spring
  2. 编写配置文件
  3. 测试

12.1 mybatis

  1. 编写实体类

  2. 编写核心配置文件

    
    
    
    <configuration>
    
    
        <typeAliases>
            <package name="com.zyq.pojo"/>
        typeAliases>
    
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false&serverTimezone=UTC"/>
                    <property name="username" value="root"/>
                    <property name="password" value="0314"/>
                dataSource>
            environment>
        environments>
        <mappers>
            <mapper class="com.zyq.mapper.UserMapper">mapper>
        mappers>
    
    configuration>
    
  3. 编写接口

  4. 编写Mapper.xml

  5. 测试

    https://blog.csdn.net/lmy86263/article/details/71189485 静态资源过滤问题

12.2 Mybatis-Spring

  1. 编写数据源配置(spring-dao.xml)

    
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="com.mysql.jdbc.Driver">property>
            <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false&serverTimezone=UTC">property>
            <property name="username" value="root">property>
            <property name="password" value="0314">property>
        bean>
    
  2. sqlSessionFactory(spring-dao.xml)

    
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource">property>
    
            <property name="configLocation" value="classpath:mybatis-config.xml">property>
            <property name="mapperLocations" value="com/zyq/mapper/*.xml">property>
        bean>
    
  3. sqlSessionTemplate(spring-dao.xml)

    
        <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
    
            <constructor-arg index="0" ref="sqlSessionFactory"/>
        bean>
    
  4. 需需要给接口加实现类(UserMapperImpl.java)

    public class UserMapperImpl implements UserMapper {
        // 所有的操作, 原来都使用sqlSession来执行, 现在都是用SQLSessionTemplate
        private SqlSessionTemplate sqlSession;
        public void setSqlSession(SqlSessionTemplate sqlSession) {
            this.sqlSession = sqlSession;
        }
        @Override
        public List<User> selectUser() {
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            return mapper.selectUser();
        }
    }
    
  5. 将实现类注入到Spring中(spring-dao.xml)

    <bean id="userMapper" class="com.zyq.mapper.UserMapperImpl">
        <property name="sqlSession" ref="sqlSession">property>
    bean>
    
    
  6. 测试使用

    ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");
    UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
    for (User user : userMapper.selectUser()) {
        System.out.println(user);
    }
    

13 声明式事务

1 事务

  • 把一组业务当成一个业务来做, 要么都成功, 要么都失败
  • 事务在项目开发中, 十分重要, 涉及到数据的一致性问题, 不能马虎
  • 确保完整性和一致性

事务的ACID原则

  • 原子性Atomicity
  • 一致性Consistency
  • 独立性Isolation
    • 多个业务可能操作同一个资源, 防止数据损坏
  • 持久性Durability
    • 事务一旦提交, 无论系统发生什么问题, 结果都不会再被影响, 被持久化地写到存储器中

2 spring中的事务管理

  • 声明式事务: AOP的一种应用

    • 实现

          
          <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
              <property name="dataSource" ref="dataSource">property>
          bean>
      
          
          
          <tx:advice id="txAdvice" transaction-manager="transactionManager">
      
      
              <tx:attributes>
                  <tx:method name="add" propagation="REQUIRED"/>
                  <tx:method name="delete" propagation="REQUIRED"/>
                  <tx:method name="update" propagation="REQUIRED"/>
                  <tx:method name="query" read-only="true"/>
                  <tx:method name="*" propagation="REQUIRED"/>
              tx:attributes>
          tx:advice>
      
          <aop:config>
              <aop:pointcut id="txPointCut" expression="execution(* com.zyq.mapper.*.*(..))"/>
              <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut">aop:advisor>
          aop:config>
      
  • 编程式事务: 需要在代码中进行事务的管理

为什么需要事务?

  • 如果不配置事务, 可能存在数据提交不一致的情况
  • 如果不在Spring中配置声明式事务, 就需要在代码中手动配置事务
  • 事务十分重要, 涉及到数据的一致性和完整性

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