Spring的AOP开发简单示例

SpringAOP支持方法级别的增强。
大致有
@Before:方法执行前执行
@After:方法执行后还没有返回时执行
@Around:环绕通知,在Before之前,在After之前。
@AfterReturning:方法返回结果之后执行
@AfterThrowing:返回异常时执行
@ @DeclareParents:给类增加接口
假设 增强service包下的所有方法 :
目录结构 :
在这里插入图片描述
切面类:

package com.fuyouj.aspect;

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

/**
 * @Desc
 * @Author FuYouJ
 * @date 2020/5/30 22:27
 */
@Aspect
@Component
public class ServiceAspect {
    //定义需要切割的地方,下面的表达式的意思是 所有限制类型的  service 包下的所有类的所有方法(任意个数参数)
    @Pointcut(value = "execution(* com.fuyouj.service..*.*(..))")
    public void embed(){}
    //方法执行前执行
    @Before("embed()")
    public void before(JoinPoint joinPoint){
        System.out.println("开始调用"+joinPoint);
    }
    //执行完成还没有返回时执行
    @After("embed()")
    public void after(JoinPoint joinPoint){
        System.out.println("调用完成"+joinPoint);
    }

    /**
     * 通过环绕通知达到检测运行时的目的
     * @param joinPoint
     * @return
     */
    @Around("embed()")
    public Object around(JoinPoint joinPoint){
        long start = System.currentTimeMillis();
        //返回值
        Object returnValue = null;
        System.out.println("开始计时"+joinPoint);
        ProceedingJoinPoint point = (ProceedingJoinPoint) joinPoint;
        System.out.println("环绕完毕");
        try {
            returnValue = point.proceed();
        } catch (Throwable throwable) {
            System.out.println("执行失败,结束计时"+joinPoint);
            throwable.printStackTrace();
        }
        finally {
            long end = System.currentTimeMillis();
            System.out.println("耗时"+(end - start));

        }
        return  returnValue;
    }
//方法返回结果之后执行
    @AfterReturning(pointcut = "embed()",returning = "returnValue")
    public void afterReturning(JoinPoint joinPoint,Object returnValue){
        System.out.println("无论为空还是有值都会返回" + joinPoint + "返回值" + returnValue);
    }
    //返回异常时执行
    @AfterThrowing(pointcut = "embed()",throwing = "exception")
    public void afterThrowing(JoinPoint joinPoint,Exception exception){
        System.out.println(joinPoint+"抛出了异常"+exception.getMessage());
    }
    /**
     * 给类增加实现接口和接口的默认实现类
     */
    @DeclareParents(value = "com.fuyouj.controller..*",defaultImpl = com.fuyouj.aspect.ParentImpl.class)
    public Parent parent;
}

控制器里面调用service的方法

@Controller
public class HelloController {
    @Autowired
    private HelloService helloService;
    public void handleRequest(){
        helloService.sayHello();
        helloService.justWantToThrowException();
    }
}
@Controller
public class HiController {
    @Autowired
    private HiService hiService;
    public void handleRequest(){
        hiService.sayHi();
        System.out.println(hiService.justWantToSayHi());
    }
}

两个service

@Service
public class HelloServiceImpl implements HelloService {
    @Override
    public void sayHello() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Hello everyOne");
    }

    @Override
    public void justWantToThrowException() {
        throw new RuntimeException("抛出一个hello Exception");
    }
}
@Service
public class HiServiceImpl implements HiService {
    @Override
    public void sayHi() {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Hi everyOne");
    }

    @Override
    public String justWantToSayHi() {
        return "justWantToSayHi";
    }
}

定义增强控制器的接口

public interface Parent {
    void parentMethod();
}
接口实现类
public class ParentImpl implements Parent {
    @Override
    public void parentMethod() {
        System.out.println("额外增加的方法执行了");
    }
}

不转换接口执行

@Configuration
@ComponentScan("com.fuyouj")
//识别AOP
@EnableAspectJAutoProxy
public class Entrance {
    public static void main(String[] args) {
       ApplicationContext applicationContext =  new AnnotationConfigApplicationContext(Entrance.class);
        HelloController helloController = (HelloController) applicationContext.getBean("helloController");
//        ((Parent)helloController).parentMethod();
        helloController.handleRequest();
        HiController hiController = (HiController) applicationContext.getBean("hiController");
        hiController.handleRequest();
    }
}

执行结果:

开始计时execution(void com.fuyouj.service.HelloService.sayHello())
环绕完毕
开始调用execution(void com.fuyouj.service.HelloService.sayHello())
Hello everyOne
耗时2001
调用完成execution(void com.fuyouj.service.HelloService.sayHello())
无论为空还是有值都会返回execution(void com.fuyouj.service.HelloService.sayHello())返回值null
开始计时execution(void com.fuyouj.service.HelloService.justWantToThrowException())
环绕完毕
开始调用execution(void com.fuyouj.service.HelloService.justWantToThrowException())
执行失败,结束计时execution(void com.fuyouj.service.HelloService.justWantToThrowException())
耗时1
调用完成execution(void com.fuyouj.service.HelloService.justWantToThrowException())
无论为空还是有值都会返回execution(void com.fuyouj.service.HelloService.justWantToThrowException())返回值null
开始计时execution(void com.fuyouj.service.HiService.sayHi())
环绕完毕
开始调用execution(void com.fuyouj.service.HiService.sayHi())
java.lang.RuntimeException: 抛出一个hello Exception
	at com.fuyouj.service.impl.HelloServiceImpl.justWantToThrowException(HelloServiceImpl.java:25)
	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:344)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:56)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)
	at com.fuyouj.aspect.ServiceAspect.around(ServiceAspect.java:44)
	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.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
	at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:47)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:55)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
	at com.sun.proxy.$Proxy27.justWantToThrowException(Unknown Source)
	at com.fuyouj.controller.HelloController.handleRequest(HelloController.java:18)
	at com.fuyouj.controller.HelloController$$FastClassBySpringCGLIB$$71d20363.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
	at org.springframework.aop.support.DelegatePerTargetObjectIntroductionInterceptor.doProceed(DelegatePerTargetObjectIntroductionInterceptor.java:119)
	at org.springframework.aop.support.DelegatePerTargetObjectIntroductionInterceptor.invoke(DelegatePerTargetObjectIntroductionInterceptor.java:107)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
	at com.fuyouj.controller.HelloController$$EnhancerBySpringCGLIB$$13848a28.handleRequest(<generated>)
	at com.fuyouj.Entrance.main(Entrance.java:47)
Hi everyOne
耗时3001
调用完成execution(void com.fuyouj.service.HiService.sayHi())
无论为空还是有值都会返回execution(void com.fuyouj.service.HiService.sayHi())返回值null
开始计时execution(String com.fuyouj.service.HiService.justWantToSayHi())
环绕完毕
开始调用execution(String com.fuyouj.service.HiService.justWantToSayHi())
耗时0
调用完成execution(String com.fuyouj.service.HiService.justWantToSayHi())
无论为空还是有值都会返回execution(String com.fuyouj.service.HiService.justWantToSayHi())返回值justWantToSayHi
justWantToSayHi

Process finished with exit code 0

只测试给类增加接口

 public static void main(String[] args) {
       ApplicationContext applicationContext =  new AnnotationConfigApplicationContext(Entrance.class);
      
        HelloController helloController = (HelloController) applicationContext.getBean("helloController");
        ((Parent)helloController).parentMethod();
    }

运行
在这里插入图片描述
Spring的对一个地方多个AOP执行顺序如下图:
在这里插入图片描述
满足文章开头说的顺序,其实如果记不住这个图,还有个更好的记忆方式。
想象成同心圆。
在这里插入图片描述
先开始的后结束,后开始的先结束。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章