美文网首页
Spring AOP(1)

Spring AOP(1)

作者: ShawnCaffeine | 来源:发表于2021-06-08 11:12 被阅读0次

    首先我们先来一个简单到不能简单的服务接口:

    HelloService.java
    package com.jd.www.jpl.service;
     
    public interface HelloService {
            public void sayHello();
    }
    

    以及实现类

    HelloServiceImpl.java
    package com.jd.www.jpl.service.impl;
     
    import com.jd.www.jpl.service.HelloService;
     
    public class HelloServiceImpl implements HelloService {
     
        @Override
        public void sayHello() {
            System.out.println("hello world!!");
        }
    }
    

    接着创建一个拦截器接口

    Interceptor.java
    package com.jd.www.jpl.common.aop.proxy;
     
    public interface Interceptor {
        // 前置通知
        void before();
     
        // 是否采用环绕通知
        boolean useAround();
     
        // 环绕通知
        Object around(Object target, Method method, Object[] args)
                throws IllegalAccessException, IllegalArgumentException, InvocationTargetException;
     
        // 事后方法
        void after();
     
        // 异常返回方法
        void afterThrowing();
     
        // 正常返回方法
        void afterReturning();
     
    }
    

    依据这个接口,可以给出一个很简单的实现

    MyInterceptor.java
    package com.jd.www.jpl.common.aop.proxy.impl;
    
    import com.jd.www.jpl.common.aop.proxy.Interceptor;
    
    public class MyInterceptor implements Interceptor {
        @Override
        public void before() {
            System.out.println("事前通知");
        }
    
        @Override
        public boolean useAround() {
            return true;
        }
    
        @Override
        public Object around(Object target, Method method, Object[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
            System.out.println("环绕通知before");
            Object o = method.invoke(target,args);
            System.out.println("环绕通知after");
            return o;
        }
    
        @Override
        public void after() {
            System.out.println("事后通知");
        }
    
        @Override
        public void afterThrowing() {
            System.out.println("异常返回通知"); 
        }
    
        @Override
        public void afterReturning() {
            System.out.println("正常返回通知");
        }
    }
    
    

    如果用proxy去调用方法,约定如下:

    1、首先调用拦截器的before方法;

    2、如果拦截器的useAround方法,返回为true,则执行拦截器的around方法,不执行target对象原有的sayHello方法;

    3、无论结果如何都会执行拦截器的after方法;

    4、如果around方法有异常或者原有的target对象的sayHello方法有异常,则执行拦截器的afterThrowing方法,否则执行afterReturning方法。

    好了,为了更好的说明,我们来个流程图。

    流程图

    对应的ProxyBean

    package com.jd.www.jpl.common.aop.proxy.impl;
    
    public class ProxyBean implements InvocationHandler {
    
        private Object target;
        private Interceptor interceptor;
    
        public static Object getProxyBean(Object target, Interceptor interceptor){
            ProxyBean proxyBean = new ProxyBean();
            proxyBean.target = target;
            proxyBean.interceptor = interceptor;
            return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),proxyBean);
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            boolean e = false;
            Object ret = null;
            MyInterceptor myInterceptor = new MyInterceptor();
            myInterceptor.before();
            try {
                if(interceptor.useAround()){
                    ret = myInterceptor.around(target,method,args);
                }else {
                    ret = method.invoke(target,args);
                }
            } catch (InvocationTargetException | IllegalAccessException | IllegalArgumentException ex) {
                e = true;
            }
            myInterceptor.after();
            if(e){
                myInterceptor.afterThrowing();
            }else{
                myInterceptor.afterReturning();
                return ret;
            }
            return null;
        }
    }
    

    创建测试用例

    SpringAopTest.java
    package com.jd.jmq.consumer;
    
    import com.jd.www.jpl.common.aop.proxy.impl.MyInterceptor;
    import com.jd.www.jpl.common.aop.proxy.impl.ProxyBean;
    import com.jd.www.jpl.service.HelloService;
    import com.jd.www.jpl.service.impl.HelloServiceImpl;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = {"classpath*:spring/spring-consumer.xml"})
    public class SpringAopTest {
        @Test
        public void testAop(){
            HelloService helloService = new HelloServiceImpl();
            HelloService proxy = (HelloService) ProxyBean.getProxyBean(helloService,new MyInterceptor());
            proxy.sayHello();
        }
    }
    

    运行结果:


    结果

    相关文章

      网友评论

          本文标题:Spring AOP(1)

          本文链接:https://www.haomeiwen.com/subject/cjcosltx.html