Spring开发核心之AOP的实现与切入点持久化

Spring开发核心之AOP的实现与切入点持久化

什么是AOP

将一个大的功能划分为小的功能单元,然后将这些小的功能进行组合,就构成了一个完整的大功能。在划分功能单元的时候,要考虑到它们的通用性。这种技术称为模块化设计,也称为面向切面编程(AOP)

AOP的实现

Spring中AOP的实现主要是通过动态代理的方式来实现的。Spring可以为普通的类以及接口生成动态代理,以增强类的功能。

代理样例

以下面代码为例:

package com.example.demo;

public interface TestService {
    void doSomething();
}

完成代理:

package com.example.demo;

public class TestServiceProxy implements InvocationHandler {
    private Object target;

    public Object bind(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), 
                                      target.getClass().getInterfaces(),
                                      this);
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("方法执行前");
        Object result = method.invoke(target, args);
        System.out.println("方法执行后");
        return result;
    }
}

在这个代理中,我们使用了代理对象和被代理的原始对象。利用这种方式,增强了原始对象的功能。

Spring AOP实现

Spring中使用AOP代理主要有两种方式:

  1. 基于proxy:使用JDK自带的Proxy类实现代理,这种方式只能代理接口,不能代理类;
  2. 基于aspect:基于Aspectj框架实现织入,可以代理接口和类。

使用proxy示例:

在Spring AOP中,我们可以通过实现Interceptor接口来实现增强方法,Interceptor有两个主要的执行方法——preHandle和afterCompletion。

假设我们有一个类:

@Service
public class TestService {
    public void doSomething() {
        System.out.println("do something!");
    }
}

为这个类添加一个拦截器:

@Aspect
@Component
public class TestAspect {
    @Pointcut("execution(* com.example.demo.TestService.*(..))")
    public void testMethod() {}

    @Before("testMethod()")
    public void doBefore() {
        System.out.println("方法执行前...");
    }

    @After("testMethod()")
    public void doAfter() {
        System.out.println("方法执行后...");
    }
}

在这个例子中,我们使用了@Aspect和@Pointcut两个注解。@Aspect表示这个类为切面类,@Pointcut表示定义一个切入点,拦截TestService类的所有方法。

使用aspect示例:

定义切面类:

@Aspect
@Component
public class AspectTest {
    @Pointcut("execution(* com.example.demo.Test.*(..))")
    public void testMethod() {}

    @Around("testMethod()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("方法执行前...");
        Object result = pjp.proceed();
        System.out.println("方法执行后...");
        return result;
    }
}

当我们使用基于aspect的方式时,我们需要定义切面类,并且使用@Aspect注解,@Pointcut注解定义需要织入的切入点,@Around注解则定义需要增强的方法。

AOP切入点持久化

在AOP中,我们经常需要使用切入点。但是,如果我们有多个切面类,而切入点又是一样的,这就会带来不必要的重复工作。所以,我们可以将一些切入点持久化,方便以后的使用。

Spring提供了两种方式来实现切入点的持久化:使用@Aspect标记或是在XML配置文件中进行定义。

@Aspect标记

  1. 定义切面接口:
package com.example.demo.advice;

public interface ICommonAdvice {
}
  1. 定义基础切面类,需要实现切面接口:
package com.example.demo.advice;

@Aspect
@Component
public abstract class BasicAdvice implements ICommonAdvice {
}

使用@Aspect标记这个类,加上@Component注解,表示这是一个切面类,并且需要实现切面接口。

  1. 在子切面类中继承并声明切入点:
package com.example.demo.advice;

@Aspect
@Component
public class TestAdvice extends BasicAdvice {
    @Pointcut("execution(* com.example.demo.Test.*(..))")
    public void testMethod() {}

    @Around("testMethod()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("方法执行前...");
        Object result = pjp.proceed();
        System.out.println("方法执行后...");
        return result;
    }
}

在子切面类中,我们可以继承父切面类,并声明自己的切入点。

XML配置

在XML配置文件中进行定义

  1. 在XML配置文件中引入AOP的命名空间
<bean xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
  1. 定义切入点:
<aop:pointcut expression="execution(* com.example.demo.Test.*(..))" id="testMethod" />
  1. 定义增强方法:
<aop:aspect ref="testAspect">
    <aop:around method="doAround" pointcut-ref="testMethod" />
</aop:aspect>

在这个例子中,我们定义了一个切入点,拦截Test类的所有方法。同时,我们定义了在Test类中应用切面的类TestAspect。我们使用标签来为 Test 添加增强方法doAround。

总结

本文介绍了AOP的实现方式及切入点的持久化方式。AOP实现主要基于动态代理,Spring中实现AOP一般有两种方式:使用@Aspect标记或是在XML文件中进行定义。切入点的持久化可以避免重复定义相同的切入点,减轻工作量,提高效率。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring开发核心之AOP的实现与切入点持久化 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • 启动Spring项目详细过程(小结)

    启动Spring项目详细过程 启动一个Spring项目可以分为以下几个步骤: 1. 创建项目 在IDE中创建一个新的Spring项目,可以选择使用Spring Initializr或手动创建。 使用Spring Initializr Spring Initializr是一个Web UI,可以用来方便地创建Spring项目。 打开Spring Initiali…

    Java 2023年5月19日
    00
  • java(包括springboot)读取resources下文件方式实现

    下面是详细讲解“java(包括springboot)读取resources下文件方式实现”的完整攻略。 1. 背景 在Java中,经常需要读取resources下的文件。resources文件夹通常位于项目的classpath下,可以存放各种类型的文件,如文本文件、配置文件、图片等。这里将对读取resource文件夹下文件的几种常用方法进行讲解。 2. 使用…

    Java 2023年5月19日
    00
  • jdbc连接数据库实例详解

    JDBC连接数据库实例详解 在Java程序中,经常需要与数据库进行交互。JDBC(Java Database Connectivity)是Java开发中用于连接和操作数据库的标准API。本文将详细介绍JDBC连接数据库的相关知识,包括JDBC连接步骤、示例代码等。 JDBC连接步骤 JDBC连接数据库的基本步骤如下: 加载数据库驱动 连接数据库 创建Stat…

    Java 2023年5月19日
    00
  • day01-项目介绍&功能实现

    项目介绍&功能实现 1.项目介绍&环境搭建 一个以社交平台为核心的轻电商项目,功能如下: 短信登录、商户查询缓存、优惠券秒杀、达人探店、好友关注、附近的商户、用户签到、UV统计 1.1项目架构 1.2项目环境搭建 1.2.1后端项目搭建 mysql的版本采用5.7及以上版本 (1)首先创建数据库,需要创建的表有: tb_user:用户表 tb…

    Java 2023年4月19日
    00
  • Spring MVC+FastJson+Swagger集成的完整实例教程

    Spring MVC+FastJson+Swagger集成的完整实例教程 Spring MVC是一个非常流行的Java Web框架,它提供了很多方便的功能。FastJson是一个高性能的JSON库,它可以将Java对象转换为JSON格式的字符串。Swagger是一个API文档生成工具,它可以自动生成API文档,并提供交互式API测试界面。本文将详细讲解如何使…

    Java 2023年5月17日
    00
  • Bootstrap和Java分页实例第一篇

    首先,该攻略主要针对的是Bootstrap和Java分页实例的基础入门教程,对于前端和Java开发初学者非常实用。文本将分为以下几个部分进行讲解: 一、Bootstrap的基础使用 1.1 引入Bootstrap到项目中 在使用Bootstrap进行开发时,首先需要在项目中引入Bootstrap的CSS和JS文件,这可以通过CDN链接或者下载本地文件的方式引…

    Java 2023年6月15日
    00
  • Java整型数与网络字节序byte[]数组转换关系详解

    Java整型数与网络字节序byte[]数组转换是进行网络通信时常见的操作。本攻略将通过对Java整型数与网络字节序byte[]数组转换原理的分析,来详细讲解转换的方法和过程。 网络字节序 在网络通信中,字节序(byte order)是指多字节数据进行交换时字节的排列顺序。网络通信中使用的字节序通常是大端序(big-endian)和小端序(little-end…

    Java 2023年5月26日
    00
  • 解析spring-boot-starter-parent简介

    让我来详细讲解一下“解析spring-boot-starter-parent简介”的攻略。 标题 1. 简介 spring-boot-starter-parent是Spring Boot的一个parent pom,它包含许多通用的配置和依赖项,可以让我们更方便地创建基于Spring Boot的项目。在创建一个标准的Spring Boot项目时,一般都会继承s…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部