Spring AOP

Sping AOP

什么是AOP

AOP(Aspect Oriented Programming)意为面向切面编程。

一种通过预编译方式和运行期动态代理实现程序功能的统一维护的技术。

对业务逻辑各个部分隔离,降低耦合度,提高重用性,开发效率。

主要功能:日志记录,性能统计,安全控制,事务处理,异常处理等。

底层实现原理是JDK动态代理和CGLIB动态代理。前者必须实现接口,后者直接操纵字节码。

AOP与OOP

OOP面向对象编程,对业务处理过程的实体及其属性,行为进行抽象封装。

AOP面向切面编程,对业务处理过程中的切面提取。

AOP术语

连接点(Joinpoint)

AOP用来标记插入代码的特定位置(方法调用前,方法调用后,方法调用前后,抛出异常)

切点(Pointcut)

AOP查询连接点的方式,一个切点可以匹配一个或多个连接点。

增强(Advice)

AOP插入连接点的一段代码,同时包括方位信息。结合方位信息和切点信息可以查询到目标连接点。

引介(Introduction)

一种特殊的增强,可以为类添加属性和方法。一个业务类原本没有实现某接口,通过引介,动态地为该业务添加接口的实现逻辑,使得该业务成为这个接口的实现类。

织入(Weaving)

插入代码的过程,包括以下三种:

编译器织入

需要特殊编译器

类装载器织入

需要特殊的类装载器

动态代理织入

切面(Aspect)

由切点和增强组成

目标对象(Target)

增强逻辑的织入目标类。

代理(proxy)

一个类被AOP织入增强以后,产生结果类,该结果类融合了原类和增强逻辑

切点表达式

execution(返回类型 类全名 方法名 (形参列表))

  • (*):代表任意字符,匹配上下文中某元素。

  • (..):代表任意字符,可表示多个元素,表示类时不能单独使用,必须和*配合,代表形参时可以单独使用。

  • (+):代表按类型匹配指定类的所有类(包括子类)只能跟在类名之后。

切面类型

StaticMethodMacherPointcutAdvice(静态切面)

代表一个静态方法匹配切面,通过StaticMethodMacherPointcut定义切点,通过类活驴和方法名匹配定义切点,需继承该类切面,提供匹配类过滤和方法匹配的规则。

DynamicMethodMacherPointcut(动态切面)

抽象类,将isRuntime()方法设置为final ,且返回true,这样其继承子类就一定是一个动态的切点。该抽象类默认匹配所有类和方法,实现切面需继承该类

Spring AOP框架

纯Java实现,不需专门编译过程,类装载器。运行期通过代理的方式向目标类织入增强代码。

包含两种代理机制:

JDK 动态代理和CGLib 动态代理

均为 Spring AOP 底层技术。

使用方式:基于XML配置文件;基于注解

<!– 开启 AOP 注解开关 -->
<aop:aspectj-autoproxy  />
  • @Aspect 注解:放置于切面类上,用于注解定义一个切面

  • @Before 注解:放置于切面类方法上,用于注解实现前置增强

  • @After 注解:放置于切面类方法上,用于注解实现后置增强

  • @Around 注解:放置于切面类方法上,用于注解实现环绕增强

  • @AfterThrowing 注解:放置于切面类方法上,用于注解实现抛出异常增强

切点表达式

实例

Dynamic proxy(动态代理)

Chinese

package proxy_pattern.dynamic_proxy;

public class Chinese implements IPerson{

  @Override
  public void study() {
      System.out.println("中国人爱学习");
  }

  @Override
  public void think() {
      System.out.println("中国人爱思考");
  }
}

ChineseProxyTest

package proxy_pattern.dynamic_proxy;

import java.lang.reflect.Proxy;

public class ChineseProxyTest {
  public static void main(String[] args){
      Chinese chinese = new Chinese();
      MyInvocationHandler handler= new MyInvocationHandler(chinese);
      IPerson person = (IPerson) Proxy.newProxyInstance(
              chinese.getClass().getClassLoader(),
              chinese.getClass().getInterfaces(),
              handler                   //返回代理对象
              //代理对象自动执行接口,即9行的 person
      );
      person.study();
      person.think();
  }
}

IPerson

package proxy_pattern.dynamic_proxy;

public interface IPerson {
  void study();
  void think();

}

MyInvocationHandler

package proxy_pattern.dynamic_proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler {
  private Object target;//目标对象
  public MyInvocationHandler(Object target){
      this.target = target;
  }
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      System.out.println(method.getName()+"方法开始执行");//前置增强
      Object result = method.invoke(target,args);//调用目标对象的方法
      System.out.println(method.getName()+"方法结束执行");//后置增强
      return result;
  }
}

static proxy(静态代理)

DogProxy

package proxy_pattern.static_proxy;

public class DogProxy implements IDog {
  public IDog target;
  public DogProxy(IDog target){
      this.target=target;
  }
  @Override
  public void bark(){
      System.out.println("bark方法开始执行");
      target.bark();
      System.out.println("bark方法结束执行");
  }
  @Override
  public void run(){
      System.out.println("run方法开始执行");
      target.run();
      System.out.println("run方法结束执行");
  }
}

DogProxyTest

package proxy_pattern.static_proxy;

public class DogProxyTest {
  public static void main(String[] args){
      DogProxy dogProxy= new DogProxy(new Hiromi());
      dogProxy.bark();
      dogProxy.run();
      System.out.println("------------");
      DogProxy dogProxy2=new DogProxy(new Huskie());
      dogProxy2.bark();
      dogProxy2.run();
  }
}

Hiromi

package proxy_pattern.static_proxy;

public class Hiromi implements IDog {
  @Override
  public void bark(){
      System.out.println("博美狗叫");
  }
  @Override
  public void run(){
      System.out.println("博美跑");
  }
}

Huskie

package proxy_pattern.static_proxy;

public class Huskie implements IDog {
  @Override
  public void bark(){
      System.out.println("哈士奇狗叫");
  }
  @Override
  public void run(){
      System.out.println("哈士奇在跑");
  }
}

IDog

package proxy_pattern.static_proxy;

public interface IDog {
  void bark();
  void run();
}

aop ioc(ioc容器)


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--开启自动扫描Bean-->
    <context:component-scan base-package="aop"/>
    <aop:aspectj-autoproxy/>

</beans>

__EOF__

本文作者3DG
本文链接https://www.cnblogs.com/3-DG/p/17745326.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   3DG  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示