Spring AOP的几种实现方式

1.通过注解实现

1.1导入依赖

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.1.6.RELEASE</version>
        </dependency>

1.2定义注解

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TestAnnotation{
}

1.2定义切面类

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/*
* 切面类
**/
@Aspect
@Component
public class AnnotationAspect {

    // 定义一个切点:所有被RequestMapping注解修饰的方法会织入advice
    @Pointcut("@annotation(TestAnnotation)")
    private void advicePointcut() {}

    /*
    * 前置通知
    **/
    @Before("advicePointcut()")
    public void before() {
        System.out.println("annotation前置通知");
    }

    @After("advicePointcut()")
    public void after() {
        System.out.println("annotation后置通知");
    }

    @AfterReturning(pointcut = "advicePointcut()")
    public void afterReturning() {
        System.out.println("annotation后置返回通知");
    }

    @AfterThrowing(pointcut = "advicePointcut()", throwing = "ex")
    public void afterThrowing(Exception ex) throws Exception {
        System.out.println("annotation异常通知");
        System.out.println(ex.getMessage());
    }

    @Around("advicePointcut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        Object proceed = null;
        if (!"".equals("admin")) {
            System.out.println("annotation环绕前置");
            proceed = pjp.proceed(pjp.getArgs());
            System.out.println("annotation环绕后置");
        }
        return proceed;
    }
}

2.jdk代理注解方式

2.1.定义接口


public interface TargetInteface {
    void method1();
    void method2();
    int method3(Integer i);
}

2.2.实现接口

public class Target implements TargetInteface{

    /*
    * 需要增强的方法,连接点JoinPoint
    **/
    public void method1() {
        System.out.println("method1 running ...");
    }

    public void method2() {
        System.out.println("method2 running ...");
    }

    public int method3(Integer i) {
        System.out.println("method3 running ...");
        return i;
    }
}

2.3.定义通知

public class TargetAdvice implements MethodInterceptor, MethodBeforeAdvice, AfterReturningAdvice {

    /*
    * 通知/增强
    **/
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        System.out.println("前置环绕通知");
        Object proceed = methodInvocation.proceed();
        System.out.println("后置环绕通知");
        return proceed;
    }

    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("后置返回通知");
    }

    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("前置通知");
    }
}

2.4.书写配置文件

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

    <bean id="target" class="com.heaboy.aopdemo.aop.Target"/>

    <bean id="targetAdvice" class="com.heaboy.aopdemo.aop.TargetAdvice"/>

    <bean id="targetProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="target"/> <!--被代理的类-->
        <property name="interceptorNames" value="targetAdvice"/>  <!--如果用多种增强方式,value的值使用逗号(,)分割-->
        <property name="proxyTargetClass" value="false"/>
        <property name="interfaces" value="com.heaboy.aopdemo.aop.TargetInteface"/>  <!--target实现的接口-->
    </bean>
</beans>

2.5启动测试

public class AopTest {
    public static void main(String[] args) {
        ApplicationContext appCtx = new ClassPathXmlApplicationContext("spring-aop.xml");
        TargetInteface targetProxy = (TargetInteface) appCtx.getBean("targetProxy");
        targetProxy.method1();
        print(targetProxy);
    }
}

3.cglib配置文件方式

3.1.定义被代理的类

public class Target {

    public void method1() {
        System.out.println("method1 running ...");
    }

    public void method2() {
        System.out.println("method2 running ...");
    }

    /*
    * 连接点JoinPoint
    **/
    public int method3(Integer i) {
        System.out.println("method3 running ...");
        int i1 = 1 / i;
        return i;
    }
}

3.2.定义Aspect

import org.aspectj.lang.ProceedingJoinPoint;
/*
* 切面类
**/
public class TargetAspect {

    /*
    * 前置通知
    **/
    public void before() {
        System.out.println("conf前置通知");
    }

    public void after() {
        System.out.println("conf后置通知");
    }

    public void afterReturning() {
        System.out.println("conf后置返回通知");
    }

    public void afterThrowing(Exception ex) throws Exception {
//        System.out.println("conf异常通知");
//        System.out.println(ex.getMessage());
    }

    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        Object proceed = null;
        if (!"".equals("admin")) {
            System.out.println("conf环绕前置");
            proceed = pjp.proceed(pjp.getArgs());
            System.out.println("conf环绕后置");
        }
        return proceed;
    }
}

3.3书写配置文件

<?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: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 http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="target" class="com.heaboy.aopdemo.confaop.Target"/>

    <bean id="targetAspect" class="com.heaboy.aopdemo.confaop.TargetAspect"/>

    <!--proxy-target-class="true" 表示使用cglib代理.默认为false,创建有接口的jdk代理-->
    <aop:config proxy-target-class="true">
        <!--切面:由切入点和通知组成-->
        <aop:aspect ref="targetAspect">
            <!--切入点 pointcut-->
            <aop:pointcut id="pointcut" expression="execution(* com.heaboy.aopdemo.confaop.*.*(..))"/>
            <!--增强/通知 advice-->
            <aop:before method="before" pointcut-ref="pointcut"/>
            <aop:after method="after" pointcut-ref="pointcut"/>
            <aop:around method="around" pointcut-ref="pointcut"/>
            <aop:after-returning method="afterReturning" pointcut-ref="pointcut"/>
            <aop:after-throwing method="afterThrowing" throwing="ex" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>
</beans>

3.4启动测试

public class AopTest {
    public static void main(String[] args) {
        ApplicationContext appCtx = new ClassPathXmlApplicationContext("spring-confaop.xml");
        Target targetProxy = (Target) appCtx.getBean("target");
        System.out.println(targetProxy.method3(1));
    }
}

相关推荐

  1. 分布式锁实现方式

    2024-07-11 20:50:05       45 阅读
  2. 分布式 ID 实现方式

    2024-07-11 20:50:05       56 阅读
  3. 分布式锁实现方式

    2024-07-11 20:50:05       35 阅读
  4. Spring AOP实现方式

    2024-07-11 20:50:05       19 阅读
  5. SpringAOP实现原理

    2024-07-11 20:50:05       48 阅读
  6. Spring Boot 中实现跨域方式

    2024-07-11 20:50:05       57 阅读
  7. css垂直水平居中实现方式

    2024-07-11 20:50:05       52 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-11 20:50:05       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-11 20:50:05       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-11 20:50:05       58 阅读
  4. Python语言-面向对象

    2024-07-11 20:50:05       69 阅读

热门阅读

  1. pytorch 模型保存到本地之后,如何继续训练

    2024-07-11 20:50:05       22 阅读
  2. 【Spring】springSecurity使用

    2024-07-11 20:50:05       17 阅读
  3. 力扣682.棒球比赛

    2024-07-11 20:50:05       18 阅读
  4. STM32学习历程(day4)

    2024-07-11 20:50:05       20 阅读
  5. C# 装饰器模式(Decorator Pattern)

    2024-07-11 20:50:05       20 阅读
  6. 代码随想录-DAY⑦-字符串——leetcode 344 | 541 | 151

    2024-07-11 20:50:05       21 阅读
  7. FastAPI+SQLAlchemy数据库连接

    2024-07-11 20:50:05       19 阅读
  8. 关于vue监听数组

    2024-07-11 20:50:05       18 阅读
  9. SQL 自定义函数

    2024-07-11 20:50:05       22 阅读
  10. linux内核访问读写用户层文件方法

    2024-07-11 20:50:05       21 阅读
  11. RK3568平台开发系列讲解(网络篇)netfilter框架

    2024-07-11 20:50:05       19 阅读
  12. Netty服务端接收TCP链接数据

    2024-07-11 20:50:05       16 阅读