一、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:
<!--Spring AOP依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
  • 步骤二:spring-config.xml
<!-- 注解扫描-->
<context:component-scan base-package="com.sean.aoptest"></context:component-scan>
<!-- 设置aop动态代理类型:true为代理类,false为代理接口 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
  • 步骤三:编写代码,在这里我上传一段测试代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring-config-test.xml"})
public class SpringTest{ @Autowired
private Student student;
@Test
public void test01(){
System.out.println(student.say("zengxing"));
}
} @Component
class Student implements Person{ @Override
public String say(String name) {
// TODO Auto-generated method stub
// if (name.equals("zengxing")) {
// throw new RuntimeException("名字不能是" + name); //要抛出运行时异常
// }
return "Hello, " + name;
} }///*
around before...
before
around after...
after
str:Hello, zengxing
afterReturningAdvice
Hello, zengxing
*/// @Aspect
@Component
class LoggingAspect{
//前置
@Before("execution(String say(String))")
public void before(JoinPoint point){
System.out.println("before");
} //后置
@After("execution(String say(String))")
public void after(JoinPoint point){
System.out.println("after");
} //环绕
@Around("execution(String say(String))")
public Object around(ProceedingJoinPoint point) throws Throwable{
System.out.println("around before...");
Object result = point.proceed();
System.out.println("around after...");
return result;
} //返回
@AfterReturning(value="execution(String say(String))", returning="str")
public void afterReturningAdvice(JoinPoint point, String str){
System.out.println("str:" + str);
System.out.println("afterReturningAdvice");
} //抛出
@AfterThrowing(value = "execution(String say(String))", throwing = "e")
public void afterThrowingAdvice(JoinPoint point, Exception e){
String message = e.getMessage();
System.out.println(message);
System.out.println("AfterThrowingAdvice...");
}
}
  • 3.2 通过切点注解表达式(AspectJ @annotation)进行拦截

    • 开发步骤:

      • 1 定义注解类
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface AuthorityTag { }
  • 2 为切面类中增强指定注解表达式
@Aspect
@Component
class AuthorityAspect{
@Before("@annotation(com.sean.aoptest.AuthorityTag)")
public void before(JoinPoint point){
System.out.println("authority before");
}
}
  • 3 在目标类目标方法上标注注解
@Component		//将对象放入到IOC容器中
class Car1 implements Wheel{ @AuthorityTag //标注切入的的增强
@Override
public void run(){
System.out.println("I am a car, i can run");
}
}
  • 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. RabbitMQ C#客户端自动重连

    重要参考文章来源:http://gigi.nullneuron.net/gigilabs/resilient-connections-with-rabbitmq-net-client/ 参考代码:ht ...

  2. git 下载指定tag版本的源码<转>

    git clone --branch x.x.x https://xxx.xxx.com/xxx/xxx.git 原文地址:https://blog.csdn.net/weixin_30617561/ ...

  3. [转]初识NuGet - 概念, 安装和使用

    1. NuGet是什么? NuGet is a Visual Studio 2010 extension that makes it easy to add, remove, and update l ...

  4. ios 打包相关的那些报错

    这张图片是因为打包bitcode的时候出现了失败,重新打包即可 这个是因为电脑容量不足导致的无法启动模拟器,这个经常发生在128g的电脑并且同时开启多个模拟器的情况下 打完包后,苹果会给你发邮件告诉你 ...

  5. cmd find命令用法

    Windows命令行(cmd)下快速查找文件(类似Linux下find命令) 2015年04月11日 10:50:43 开水 阅读数 62240 标签: 命令行cmdwindows 更多 个人分类:  ...

  6. CentOS6非root用户下安装及配置CDH5.3.0

    #install lsb packagesudo yum install -y redhat-lsb #install net-tools package sudo yum install -y ne ...

  7. java中map和对象互转工具类的实现示例

    在项目开发中,经常碰到map转实体对象或者对象转map的场景,工作中,很多时候我们可能比较喜欢使用第三方jar包的API对他们进行转化,而且用起来也还算方便,比如像fastJson就可以轻松实现map ...

  8. Eclipse 修改(重定向)SVN地址

    由于SVN服务器IP变了,需要重定向SVN的路径 1.点击右上角1位置的按钮,然后选择需要打开的窗口(SVN资源库) 2.右击SVN资源库中的项目,选择重定向,然后修改新的URL即可 1. 进入本地s ...

  9. ubuntu连接多个realsense d435

    ubuntu连接多个realsense d435 import pyrealsense2 as rs import numpy as np import cv2 import time import ...

  10. java concurrent并发包使用

    package cn.com.zxf.atomic; import java.util.concurrent.atomic.AtomicInteger; public class AtomicExam ...