预习阶段

1.1 代理模式的分类

  • 静态代理
  • 动态代理

1.2 静态代理

  • 抽象角色:一般使用接口抽象类
  • 真实角色:被代理的角
  • 代理角色:代理真实角色,代理真实角色后,可以做一些附属操作
  • 客户:访问代理对象的人

1.3 代理模式的优点

  • 可以使真实角色的操作更加纯粹,不用去关心一些公共的业务。

  • 公共也就交给代理角色,实现业务分工。

  • 公共角色发生拓展时,方便集中管理。

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

1.4 代码步骤

  1. 接口
  2. 真实角色:实现接口
  3. 代理角色:实现接口,声明真实角色,代理角色在要实现的方法中,调用真实角色的方法
  4. 客户端访问代理角色

1.5 动态代理

  • 动态代理和静态代理角色一样
  • 动态代理是代理类是动态生成的
  • 动态代理分类
    • 基于接口:jdk—–需要了解两个类:Proxy,InvokationHandler:调用处理程序
    • 基于基类:cglib
    • java字节码实现:javasist

一,简介

1.1 什么是AOP

  • 面向切面编程,是通过预编译的方式和运行期动态代理实现程序功能统一维护的技术
  • AOP是OOP的延续,是函数式编程的一种衍生业务降耦,提高程序的重用性

1.2 作用优势

  • 作用:在不修改源码的情况下进行功能增强
  • 优势:减少重复代码,提高开发效率,并且便于维护

1.3 底层实现

  • Spring通过动态代理技术动态的生成代理对象,代理对象方法执行时进行增强接入,去调用目标方法,从而完成功能的增强

1.4 常用动态代理技术

  • JDK代理:基于接口的动态代理,需要了解两个类:Proxy,InvokationHandler调用处理程序
  • cglib代理:基于父类的动态代理

1.5 Aop在Spring中的作用

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

  • 横切关注点:跨越应用程序多个模块的方法或功能,即使,与我们业务逻辑无光的,但是我们们需要关注的部分,就是横切关注点,如日志,安全,缓存,事务等等……
  • 切面(ASPECT):横切关注点,被模块化的特殊对象,即,他是一个
    • 通知(Advice):切面必须要完成的工作,即,他是类中的一个方法
    • 目标(Target):被通知对象
    • 代理(Proxy):向目标对象应用通知之后创建的对象
    • 切入点(PrintCut):切面通知执行的“地点”的定义
    • 连接点(JoinPoint):与切入点匹配的执行点

1.6 Aop所依赖的包

1
2
3
4
5
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>

1.7 使用Spring实现Aop

1.7.1 方式一 (原生)
  • 实现MethodBeforeAdvice接口(前置增强)

  • 实现AfterReturningAdvice接口(后置增强)

  • 实现接口的类注册Bean

  • 配置aop约束

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <aop:config>
    <!--切入点:expression:表达式(要执行的位置!返回值 类名 方法名 参数)-->
    <aop:pointcut id="pointcut" expression="execution(* com.UserServiceImpl.*(..))"/>

    <!--执行环绕增加-->
    <aop:advisor advice-ref="要切入类的Bean对象" pointcut-ref="pointcut"/>
    <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>

    </aop:config>
1.7.2 方式二(常用)

依赖1.6中提到的依赖aspectjweaver

1
2
3
4
5
6
7
8
9
10
11
12
13
<!--自定义的类-->
<bean id="diy" class="自定义的类"/>
<bean id="diy" class="jilf.log.Log"></bean>
<aop:config>
<!--自定义切面类-->
<aop:aspect ref="diy">
<!--切入点,expression中匹配要增强的方法-->
<aop:pointcut id="point" expression="execution(* jilf.service.BookServiceImpl.*(..))"/>
<aop:before method="before" pointcut-ref="point"/><!--前置增强,method对应-->
<aop:after method="after" pointcut-ref="point"/>
<!--通知-->
</aop:aspect>
</aop:config>
1.7.3 方式三(注解)
  • @aspect作用在类上表示该类是一个切面

  • **@Before(“execution(* jilf.service.BookServiceImpl.*(..))”)**作用方法上,方法执行前

  • **@After(“execution(* jilf.service.BookServiceImpl.*(..))”)**作用在方法上,方法执行后

  • ```xml
    aop:aspectj-autoproxy/开启注解支持
    注册增强方法的Bean对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51

    ### 二,事务控制

    #### 2.1 事务隔离级别

    - 可以**解决事务并发**产生的问题,如**脏读,不可重复度和虚读**

    - ISOLATION_DEFAULT

    - ISOLATION_READ_UNCOMMITTED

    - ISOLATION_READ_COMMITTED

    - ISOLATION_READ_REPEATABLE_READ

    - ISOLATION_SERIALIZABLE

    #### 2.2 事务传播行为

    - REQUIRED:如果当时没有事务,就新建一个事务,如果已经存在一个事务中,加入这个事务中。一般选择(默认值)
    - SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)
    - MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常
    - REQUERS_NEW:新建事务,如果当前在事务中,把当前事务挂起
    - NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
    - NEVER:以非事务方式运行,如果当前存在事务,抛出异常
    - NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行REQUIRED类似的操作
    - 超时时间:默认值是-1,没有超时限制。如果有,以秒为单位进行设置
    - 是否只读:建议查询时设为只读

    #### 2.3 配置事务管理器

    ```xml
    <!--配置平台事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="datasource" ref="dataSource"/>
    </bean>

    <!--通知 事务的增强-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
    <tx:method name="*"/>
    </tx:attributes>
    </tx:advice>

    <!--配置事务的aop置入-->
    <aop:confid>
    <aop:pointcut id="txPointcut" expression=""/>
    <!--事务抽取-->
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"></aop:advisor>
    <aop:advisor advice-ref="txAdvice" pointcut="execution()"></aop:advisor>
    </aop:confid>

注解配置

1
2
3
4
5
6
7
8
9
10
11
@aspect
public class Log{
@Before()
public void method1(){
System.out.println("方法执行前")
}
@AfterReturning("execution(* jilf.service.BookServiceImpl.*(..))")
public void method2(){
System.out.println("方法执行后")
}
}

注解声明式事务控制的配置要点\

  • 平台事务管理器配置(xml方式)
  • 事务通知的配置(@Transactional注解配置)
  • 事务注解驱动( <tx:annotation-driven/>)