一、AOP


1 Spring AOP 的实现原理

  • 是对OOP编程方式的一种补充。翻译过来为“面向切面编程”。

  • 1 AspectJ是静态代理的增强:所谓静态代理就是AOP框架会在便一阶段生成AOP代理类,也叫编译器增强。

  • 2 使用Spring AOP

    • 与AspectJ 的静态代理不同,Spring AOP使用的是动态代理,动态代理指AOP框架不会去修改字节码,而是在内存中临时生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并在特定的切点做了增强处理,并回调原对象的方法。
    • Spring AOP中的动态代理有两种:JDK动态代理(代理必须实现一个接口)、CGLIB动态代理(代理可以不实现接口)
    • 几个概念:
      • 切面(Advisor):是AOP中的一个术语,表示从业务逻辑中分离出来的横切逻辑比如性能监控、日志处理、权限控制等

        这些功能都可以从核心的业务逻辑中抽离出去。可以解决代码耦合的问题,职责更加单一。封装了增强和切点。
      • 增强(Advice):增强代码的功能的类,横切到代码中。
      • 目标:目标方法(JDK代理)或目标类(CGLIB代理)。
      • 代理:通过ProxyFactory类生成,分为JDK代理、CGLIB代理。
      • 切点:通过一个条件来匹配拦截的类,这个条件成为切点。
      • 连接点:作为增强方法的入参,可以获取目标方法的信息。
    • 增强
      • 织入(Weaving):将切面应用到目标对象并导致代理对象创建的过程。

        • 1 前置增强(Before):在目标方法前调用。
        • 2 后置增强(AfterAdvice):在目标方法后调用。
        • 3 环绕增强(AroundAdvice):将Before和After,甚至抛出增强和返回增强合到一起。
        • 4 返回增强(AfterReturningAdvice):在方法返回结果后执行,该增强可以接收到目标方法返回的结果。
        • 5 抛出增强(AfterThrowingAdvice):在目标方法抛出对应的类型后执行,可以接收到对应的异常信息。
      • 引入增强(DeclareParentsAdvice):想让程序在运行的时候动态实现某个接口,需要引入增强。
  • 3 注解:Spring + AspectJ

    • 1 对切面类添加 @Aspect 注解将切面类和目标类放入到IOC容器中,可以通过<context:component-scan base-package=""/>进行扫描。
    • 2 添加增强方法(包括增强类型和切点表达式,以及连接点)。
    • 3 在Spring 配置文件中添加<aop:aspectj-autoproxy proxy-target-class="true"/> ,false表示只能代理接口(JDK动态代理),true表示代理类(CGLIB代理)。
    • 3.1 通过切点表达式(AspectJ execution)进行拦截

      • 步骤一:配置pox.xml:
  1. <!--Spring AOP依赖-->
  2. <dependency>
  3. <groupId>org.springframework</groupId>
  4. <artifactId>spring-aop</artifactId>
  5. <version>${spring.version}</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.springframework</groupId>
  9. <artifactId>spring-aspects</artifactId>
  10. <version>${spring.version}</version>
  11. </dependency>
  • 步骤二:spring-config.xml
  1. <!-- 注解扫描-->
  2. <context:component-scan base-package="com.sean.aoptest"></context:component-scan>
  3. <!-- 设置aop动态代理类型:true为代理类,false为代理接口 -->
  4. <aop:aspectj-autoproxy proxy-target-class="true"/>
  • 步骤三:编写代码,在这里我上传一段测试代码
  1. @RunWith(SpringJUnit4ClassRunner.class)
  2. @ContextConfiguration(locations={"classpath:spring-config-test.xml"})
  3. public class SpringTest{
  4. @Autowired
  5. private Student student;
  6. @Test
  7. public void test01(){
  8. System.out.println(student.say("zengxing"));
  9. }
  10. }
  11. @Component
  12. class Student implements Person{
  13. @Override
  14. public String say(String name) {
  15. // TODO Auto-generated method stub
  16. // if (name.equals("zengxing")) {
  17. // throw new RuntimeException("名字不能是" + name); //要抛出运行时异常
  18. // }
  19. return "Hello, " + name;
  20. }
  21. }///*
  22. around before...
  23. before
  24. around after...
  25. after
  26. str:Hello, zengxing
  27. afterReturningAdvice
  28. Hello, zengxing
  29. *///
  30. @Aspect
  31. @Component
  32. class LoggingAspect{
  33. //前置
  34. @Before("execution(String say(String))")
  35. public void before(JoinPoint point){
  36. System.out.println("before");
  37. }
  38. //后置
  39. @After("execution(String say(String))")
  40. public void after(JoinPoint point){
  41. System.out.println("after");
  42. }
  43. //环绕
  44. @Around("execution(String say(String))")
  45. public Object around(ProceedingJoinPoint point) throws Throwable{
  46. System.out.println("around before...");
  47. Object result = point.proceed();
  48. System.out.println("around after...");
  49. return result;
  50. }
  51. //返回
  52. @AfterReturning(value="execution(String say(String))", returning="str")
  53. public void afterReturningAdvice(JoinPoint point, String str){
  54. System.out.println("str:" + str);
  55. System.out.println("afterReturningAdvice");
  56. }
  57. //抛出
  58. @AfterThrowing(value = "execution(String say(String))", throwing = "e")
  59. public void afterThrowingAdvice(JoinPoint point, Exception e){
  60. String message = e.getMessage();
  61. System.out.println(message);
  62. System.out.println("AfterThrowingAdvice...");
  63. }
  64. }
  • 3.2 通过切点注解表达式(AspectJ @annotation)进行拦截

    • 开发步骤:

      • 1 定义注解类
  1. @Target(ElementType.METHOD)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @interface AuthorityTag { }
  • 2 为切面类中增强指定注解表达式
  1. @Aspect
  2. @Component
  3. class AuthorityAspect{
  4. @Before("@annotation(com.sean.aoptest.AuthorityTag)")
  5. public void before(JoinPoint point){
  6. System.out.println("authority before");
  7. }
  8. }
  • 3 在目标类目标方法上标注注解
  1. @Component //将对象放入到IOC容器中
  2. class Car1 implements Wheel{
  3. @AuthorityTag //标注切入的的增强
  4. @Override
  5. public void run(){
  6. System.out.println("I am a car, i can run");
  7. }
  8. }
  • 4 小的知识点

    • 利用方法签名编写 AspectJ 切点表达式

      • execution * com.sean.Calculator.* (…):匹配Calculator中声明的所有方法,

        第一个 * 代表任意修饰符及任意返回值。第二个 * 代表任意方法。…匹配任意数量的参数。若目标类与接口与该切面在同一个包中,可以省略包名。
      • execution public * Calculator.*(…):匹配ArithmeticCalculator 接口的所有公有方法。
      • execution public double Calculator.*(…):匹配Calculator中返回double类型数值的方法。
      • execution public double Calculator.*(double, …):匹配第一个参数为double类型的方法,…匹配任意数量任意类型的参数。
      • execution public double Calculator.*(double, double):匹配参数类型为double,double类型的方法。
    • 可以结合切点表达式使用 &&, ||, ! 来合并。如:
      • execution(void run()) || execution(void say())
    • 切面优先级:
      • 可以通过实现Ordered接口或利用@Order注解指定。
      • 1 实现Ordered接口,getOrder()方法返回的值越小,优先级越高。
      • 2 使用@Order注解,需要出现在注解中,同样是值越小优先级越高。

参考博客:https://blog.csdn.net/qq_16605855/article/details/73465865

重新学习Spring2——IOC和AOP原理彻底搞懂的更多相关文章

  1. 170511、Spring IOC和AOP 原理彻底搞懂

    Spring提供了很多轻量级应用开发实践的工具集合,这些工具集以接口.抽象类.或工具类的形式存在于Spring中.通过使用这些工具集,可以实现应用程序与各种开源技术及框架间的友好整合.比如有关jdbc ...

  2. spring的ioc与aop原理

    ioc(反向控制) 原理:    在编码阶段,既没有实例化对象,也没有设置依赖关系,而把它交给Spring,由Spring在运行阶段实例化.组装对象.这种做法颠覆了传统的写代码实例化.组装对象.然后一 ...

  3. Spring源码学习之IOC容器实现原理(一)-DefaultListableBeanFactory

    从这个继承体系结构图来看,我们可以发现DefaultListableBeanFactory是第一个非抽象类,非接口类.实际IOC容器.所以这篇博客以DefaultListableBeanFactory ...

  4. Java轻量级业务层框架Spring两大核心IOC和AOP原理

    IoC(Inversion of Control): IOC的基本概念是:不创建对象,但是描述创建它们的方式.在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务.容器负责将这些 ...

  5. spring框架DI(IOC)和AOP 原理及方案

    http://www.blogjava.net/killme2008/archive/2007/04/20/112160.html http://www.oschina.net/code/snippe ...

  6. Spring学习笔记IOC与AOP实例

    Spring框架核心由两部分组成: 第一部分是反向控制(IOC),也叫依赖注入(DI); 控制反转(依赖注入)的主要内容是指:只描述程序中对象的被创建方式但不显示的创建对象.在以XML语言描述的配置文 ...

  7. spring中IOC和AOP原理

    IoC(Inversion of Control): (1)IoC(Inversion of Control)是指容器控制程序对象之间的关系,而不是传统实现中,由程序代码直接操控.控制权由应用代码中转 ...

  8. Spring基础篇——DI/IOC和AOP原理初识

    DI(Dependency Injection),依赖注入,和我们常听说的另一个概念 IOC(控制反转)其实归根结底实现的功能是相同的,只是同样的功能站在不同的角度来阐述罢了.这里博主就不去过多的辨析 ...

  9. Spring核心 IoC和AOP原理

    1. 什么是Spring Spring是一个轻量的Java开源框架,它简化了应用开发,实现基于POJO的编程模型.它的两大核心是:IoC(控制反转),AOP(面向切面编程). 2. IoC控制反转 简 ...

随机推荐

  1. BigDecimal代码示例

    在平常开发中,如果涉及到计算,要求准确的精度,比如单价*数量=总价之类的计算,那么得用到BigDecimal. 初始化 如下: BigDecimal amount=new BigDecimal(&qu ...

  2. docker swarm和compose 的使用(阿里)

    基本的docker使用参考:Docker 入门 到部署Web 程序- (阿里面试常用的docker命令和优点) 昨天去阿里面试 问我如果给你5台服务器 如何部署docker,我说一个个拷贝,面试官听了 ...

  3. mysql一对多表结构,查询一的信息的同时统计多的数量

    res_resource_catalog表对于res_info_item表是一对多, 查询res_resource_catalog信息的同时,统计res_info_item中该条res_resourc ...

  4. leetcode 688. “马”在棋盘上的概率

    题目描述: 已知一个 NxN 的国际象棋棋盘,棋盘的行号和列号都是从 0 开始.即最左上角的格子记为 (0, 0),最右下角的记为 (N-1, N-1). 现有一个 “马”(也译作 “骑士”)位于 ( ...

  5. JAVA字符编码一:Unicode,GBK,GB2312,UTF-8概念基础

    第一篇:JAVA字符编码系列一:Unicode,GBK,GB2312,UTF-8概念基础 来源:holen'blog   对字符编码与Unicode,ISO 10646,UCS,UTF8,UTF16, ...

  6. IT项目经理都需要具备哪些能力

    发布时间:05-2009:24优质原创作者 项目经理是IT行业中比较常见的职位,工作职责主要包括三个方面,其一是资源整合任务:其二是沟通协调任务:其三是保障项目的时间周期. 资源整合能力是项目经理的重 ...

  7. 避免git clone和push时每次都需要输入用户名和密码

    有三种方式解决git clone时每次都需要输入用户名和密码, 1. SSH免密方式 使用git bash ssh-keygen或puttygen.exe生成公钥. 2. 配置全局开机存储认证信息 下 ...

  8. 【推荐】安卓模板项目AndroidProject

    [推荐]安卓模板项目AndroidProject https://github.com/getActivity/AndroidProject 安卓架构 博客地址:但愿人长久,搬砖不再有 当我们日复一日 ...

  9. SNF-软件开发机器人-免费-火爆登场-程序下载及实战配套教程免费发放

    软件开发机器人不辱使命的完成了在软件开发方面的方式方法,颠覆了传统开发,可零编程开发软件,也可二开更强大功能. 为了更好的了解和理解软件开发机器人我们以模拟用友u8系统部分供应链程序为例进行模拟. 联 ...

  10. SNF快速开发平台2020版

    SNF快速开发平台分如下子平台: 1.CS快速开发平台 2.BS快速开发平台 3.H5移动端快速开发平台 4.软件开发机器人平台 配置型开发零编程 SNF快速开发平台是一个比较成熟的.net领域的商业 ...