SpringAOP使用注解实现5种通知类型

spring aop的5种通知类型都有

Before前置通知

AfterReturning后置通知

Around环绕通知

AfterThrowing异常通知

After最终通知

首先创建接口和实现类 先测试后置通知

package com.aaa.spring.dao;



public interface UserService {

    public void insertUser();

    public void updateUser();

    public void deleteUser();

    public void find();
}
package com.aaa.spring.dao.umpl;

import com.aaa.spring.dao.UserService;
import com.aaa.spring.exception.MyException;
import org.springframework.stereotype.Component;

@Component(创建userServiceImpl bean)
public class UserServiceImpl implements UserService {
    @Override
    public void insertUser() {
        System.out.println("添加用户");
    }

    @Override
    public void updateUser() {
        System.out.println("修改用户");
    }

    @Override
    public void deleteUser() {
        System.out.println("删除用户");
    }

    @Override
    public void find() {
        System.out.println("查询用户");
    }
}

创建要在执行的方法前后的类

package com.aaa.spring.advice;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ExceptionHandler;

@Component(获取bean对象)
@Aspect(面向切面)
public class LogAdvice {
    @AfterReturning("execution(void *User(..))")(后置通知(切入点))
    public void log(JoinPoint jp){  (JoinPoint 连接点参数)
        String name=jp.getSignature().getName();(获取拦截的方法名)
        System.out.println(name+"执行之后记录成功");
    }
}

创建ApplicationContext文件

<?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 http://www.springframework
    .org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework
    .org/schema/aop/spring-aop.xsd"
> <context:component-scan base-package="com.aaa.spring"></context:component-scan>(扫描创建bean的包就是加@Component的类的所有包 <aop:aspectj-autoproxy></aop:aspectj-autoproxy>(声明以注解的方式配置spring aop) </beans>

创建测试类

package com.aaa.spring.text;

import com.aaa.spring.dao.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;



public class Text {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationcontext.xml");(获取主配置文件)
        UserService bean = (UserService)context.getBean("userServiceImpl");(获取实现类对象)
        bean.deleteUser();
        System.out.println("*****************************");
        bean.find();
        System.out.println("*****************************");
        bean.insertUser();
        System.out.println("*****************************");
        bean.updateUser();

    }
}

测试结果

五月 20, 2019 9:01:24 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@68de145: startup date [Mon May 20 21:01:24 CST 2019]; root of context hierarchy
五月 20, 2019 9:01:24 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationcontext.xml]
删除用户
deleteUser执行之后记录成功
*****************************
查询用户
*****************************
添加用户
insertUser执行之后记录成功
*****************************
修改用户
updateUser执行之后记录成功

Process finished with exit code 0

前置通知

只需要在LogAdvice 类里边再加方法

package com.aaa.spring.advice;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ExceptionHandler;

@Component
@Aspect
public class LogAdvice {
    @AfterReturning("execution(void *User(..))")
    public void log(JoinPoint jp){
        String name=jp.getSignature().getName();
        System.out.println(name+"执行之后记录成功");
    }
    @Before("execution(void *User(..))")
    public void befor(JoinPoint jp){
        String name=jp.getSignature().getName();
        System.out.println(name+"执行之前记录成功");
    }
}

测试结果

五月 20, 2019 9:08:07 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@68de145: startup date [Mon May 20 21:08:07 CST 2019]; root of context hierarchy
五月 20, 2019 9:08:08 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationcontext.xml]
deleteUser执行之前记录成功
删除用户
deleteUser执行之后记录成功
*****************************
查询用户
*****************************
insertUser执行之前记录成功
添加用户
insertUser执行之后记录成功
*****************************
updateUser执行之前记录成功
修改用户
updateUser执行之后记录成功

Process finished with exit code 0

环绕通知

只需要在LogAdvice 类里边再加方法

package com.aaa.spring.advice;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ExceptionHandler;

@Component
@Aspect
public class LogAdvice {
    @AfterReturning("execution(void *User(..))")
    public void log(JoinPoint jp){
        String name=jp.getSignature().getName();
        System.out.println(name+"执行之后记录成功");
    }
    @Before("execution(void *User(..))")
    public void befor(JoinPoint jp){
        String name=jp.getSignature().getName();
        System.out.println(name+"执行之前记录成功");
    }
    @Around("execution(void *User(..))")
    public  void around(ProceedingJoinPoint pjp){
        String name=pjp.getSignature().getName();
        System.out.println(name+"环绕执行前");
        try {
            pjp.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println(name+"环绕后执行");
    }

}

测试结果

五月 20, 2019 9:10:12 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@68de145: startup date [Mon May 20 21:10:12 CST 2019]; root of context hierarchy
五月 20, 2019 9:10:12 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationcontext.xml]
deleteUser环绕执行前
deleteUser执行之前记录成功
删除用户
deleteUser环绕后执行
deleteUser执行之后记录成功
*****************************
查询用户
*****************************
insertUser环绕执行前
insertUser执行之前记录成功
添加用户
insertUser环绕后执行
insertUser执行之后记录成功
*****************************
updateUser环绕执行前
updateUser执行之前记录成功
修改用户
updateUser环绕后执行
updateUser执行之后记录成功

Process finished with exit code 0

最终通知

只需要在LogAdvice 类里边再加方法

package com.aaa.spring.advice;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ExceptionHandler;

@Component
@Aspect
public class LogAdvice {
    @AfterReturning("execution(void *User(..))")
    public void log(JoinPoint jp){
        String name=jp.getSignature().getName();
        System.out.println(name+"执行之后记录成功");
    }
    @Before("execution(void *User(..))")
    public void befor(JoinPoint jp){
        String name=jp.getSignature().getName();
        System.out.println(name+"执行之前记录成功");
    }
    @Around("execution(void *User(..))")
    public  void around(ProceedingJoinPoint pjp){
        String name=pjp.getSignature().getName();
        System.out.println(name+"环绕执行前");
        try {
            pjp.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println(name+"环绕后执行");
    }
    @After("execution(void *User(..))")
    public  void after(JoinPoint jp){
        String name=jp.getSignature().getName();
        System.out.println(name+"最终执行记录成功");
    }

}

测试结果

五月 20, 2019 9:12:00 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@68de145: startup date [Mon May 20 21:12:00 CST 2019]; root of context hierarchy
五月 20, 2019 9:12:00 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationcontext.xml]
deleteUser环绕执行前
deleteUser执行之前记录成功
删除用户
deleteUser环绕后执行
deleteUser最终执行记录成功
deleteUser执行之后记录成功
*****************************
查询用户
*****************************
insertUser环绕执行前
insertUser执行之前记录成功
添加用户
insertUser环绕后执行
insertUser最终执行记录成功
insertUser执行之后记录成功
*****************************
updateUser环绕执行前
updateUser执行之前记录成功
修改用户
updateUser环绕后执行
updateUser最终执行记录成功
updateUser执行之后记录成功

Process finished with exit code 0

异常通知,这里我们自定义一个异常

先创建一个异常类继承RuntimeException程序异常

package com.aaa.spring.exception;

public class MyException extends  RuntimeException{
    public  MyException(String yc){
        super(yc);
    }
}

然后在LogAdvice  类里添加方法这里为了方便测试把上面的都加上了注释

package com.aaa.spring.advice;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ExceptionHandler;

@Component
@Aspect
public class LogAdvice {
   /* @AfterReturning("execution(void *User(..))")
    public void log(JoinPoint jp){
        String name=jp.getSignature().getName();
        System.out.println(name+"执行之后记录成功");
    }
    @Before("execution(void *User(..))")
    public void befor(JoinPoint jp){
        String name=jp.getSignature().getName();
        System.out.println(name+"执行之前记录成功");
    }
    @Around("execution(void *User(..))")
    public  void around(ProceedingJoinPoint pjp){
        String name=pjp.getSignature().getName();
        System.out.println(name+"环绕执行前");
        try {
            pjp.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println(name+"环绕后执行");
    }
    @After("execution(void *User(..))")
    public  void after(JoinPoint jp){
        String name=jp.getSignature().getName();
        System.out.println(name+"最终执行记录成功");
    }*/
    @AfterThrowing(pointcut = "execution(void *User(..))")
    public  void excaption(JoinPoint jp){
        String name=jp.getSignature().getName();
        System.out.println("执行"+name+"时发生异常");
    }
}

然后在实现类里抛出异常

package com.aaa.spring.dao.umpl;

import com.aaa.spring.dao.UserService;
import com.aaa.spring.exception.MyException;
import org.springframework.stereotype.Component;

@Component
public class UserServiceImpl implements UserService {
    @Override
    public void insertUser() {
       if(true){
            throw new MyException("自定义异常");
        }
        System.out.println("添加用户");
    }

    @Override
    public void updateUser() {
        System.out.println("修改用户");
    }

    @Override
    public void deleteUser() {
        System.out.println("删除用户");
    }

    @Override
    public void find() {
        System.out.println("查询用户");
    }
}

测试结果

五月 20, 2019 9:18:57 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@68de145: startup date [Mon May 20 21:18:57 CST 2019]; root of context hierarchy
五月 20, 2019 9:18:57 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationcontext.xml]
删除用户
*****************************
查询用户
*****************************
执行insertUser时发生异常
Exception in thread "main" com.aaa.spring.exception.MyException: 自定义异常
    at com.aaa.spring.dao.umpl.UserServiceImpl.insertUser(UserServiceImpl.java:12)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
    at com.sun.proxy.$Proxy7.insertUser(Unknown Source)
    at com.aaa.spring.text.Text.main(Text.java:17)

Process finished with exit code 1
原文地址:https://www.cnblogs.com/fengxiangyu/p/10896547.html