Spring AOP精选学习

Spring AOP

 1.什么是 AOP

Spring AOP精选学习

Spring是解决实际开发中的一些问题:
* AOP解决 OOP中遇到的一些问题.是 OOP的延续和扩展.

为什么学习AOP

对程序进行增强:不修改源码的情况下.
* AOP可以进行权限校验,日志记录,性能监控,事务控制.

Spring 的 AOP 的由来:

AOP最早由AOP联盟的组织提出的,制定了一套规范.Spring将 AOP思想引入到框架中,必须遵守AOP联盟
的规范.

底层实现:

代理机制:
* Spring的 AOP的底层用到两种代理机制:
* JDK的动态代理 :针对实现了接口的类产生代理.
* Cglib的动态代理:针对没有实现接口的类产生代理. 应用的是底层的字节码增强的技术 生成当前类
的子类对象.

 

2. Spring 底层 AOP 的实现原理: : (了解)

JDK 动态代理增强一个类中方法:

Spring AOP精选学习

 Cglib动态代理增强一个类中的方法:

Spring AOP精选学习

 

3. Spring 的基于 AspectJ 的 AOP 开发
     1 AOP 的开发中的相关术语:

Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在 spring中,这些点指的是方法,因为 spring只
支持方法类型的连接点.
Pointcut(切入点):所谓切入点是指我们要对哪些 Joinpoint进行拦截的定义.
Advice(通知/增强):所谓通知是指拦截到 Joinpoint之后所要做的事情就是通知.通知分为前置通知,后置
通知,异常通知,最终通知,环绕通知(切面要完成的功能)
Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下, Introduction可以在运行期为类
动态地添加一些方法或Field.
Target(目标对象):代理的目标对象
Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程.
spring采用动态代理织入,而AspectJ采用编译期织入和类装在期织入
Proxy(代理):一个类被 AOP织入增强后,就产生一个结果代理类
Aspect(切面): 是切入点和通知(引介)的结合

Spring 使用 AspectJ 进行 AOP 的开发:XML 的方式

1 引入相应的 jar 包

Spring AOP精选学习

引入 Spring 的配置文件

Spring AOP精选学习

编写目标类

Spring AOP精选学习

Spring AOP精选学习

目标类的配置

Spring AOP精选学习

整合 Junit 单元测试

Spring AOP精选学习

通知类型

前置通知(before) :在目标方法执行之前执行.
* 返回通知(afterReturing):在目标方法执行之后执行,若目标方法执行中出现异常, 则不会进入到返回通知,
只有在目标方法正常结束时,才执行的通知
* 环绕通知(around) :在目标方法执行前和执行后执行
* 异常抛出通知(afterThrowing):在目标方法执行出现 异常的时候执行
* 后置通知(after):在目标方法执行之后执行,无论目标方法是否出现异常 最终通知都会执行.

切入点表达式

execution(表达式)
表达式:
[方法访问修饰符] 方法返回值包名.类名.方法名(方法的参数)
public * com.cjy.spring.dao.*.*(..)
* com.cjy.spring.dao.*.*(..)
* com.cjy.spring.dao.UserDao+.*(..)
* com.cjy.spring.dao..*.*(..)

编写一个切面类

Spring AOP精选学习

配置完成增强

Spring AOP精选学习

 Spring 使用 AspectJ 进行 AOP  的开发: :注解方式

 引入相关的jar包

Spring AOP精选学习

引入Spring 的配置文件

Spring AOP精选学习

编写目标类

Spring AOP精选学习

开启aop 注解的自动代理

<aop:aspectj-autoproxy/>

AspectJ 的 AOP 的注解:

通知类型:
* @Before :前置通知          
* @AfterReturing:后置通知

@Around 环绕通知
* @After :最终通知
* @AfterThrowing :异常抛出通知.

@Pointcut:定义切入点的注解

编写切面类

Spring AOP精选学习

 配置切面:

Spring AOP精选学习

其他通知的注解:

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class MyAspectAnno {
    @Before("MyAspectAnno.pointcut1()")
    public void before(){
    System.out.println("前置通知===========");
    }
    @AfterReturning("MyAspectAnno.pointcut2()")
    public void afterReturning(){
    System.out.println("后置通知===========");
    }
    @Around("MyAspectAnno.pointcut3()")
    public Object around(ProceedingoinPoint joinPoint) throws Throwable{
    System.out.println("环绕前通知==========");
    Object obj = joinPoint.proceed();
    System.out.println("环绕后通知==========");
    return obj;
    }
    @AfterThrowing("MyAspectAnno.pointcut4()")
    public void afterThrowing(){
    System.out.println("异常抛出通知========");
    }
    @After("MyAspectAnno.pointcut4()")
    public void after(){
    System.out.println("最终通知==========");
    }
    @Pointcut("execution(* com.cjy.dao.ProductDao.save(..))")
    private void pointcut1(){}
    @Pointcut("execution(*com.cjy.dao.ProductDao.update(..))")
    private void pointcut2(){}
    @Pointcut("execution(* com.cjy.dao.ProductDao.delete(..))")
    private void pointcut3(){}
    @Pointcut("execution(* com.cjy.daoS.ProductDao.find(..))")
    private void pointcut4(){}
}