• AOP 增强方法


    Spring AOP 提供了 5 种类型的通知,它们分别是 Before Advice(前置通知)、After Returning Advice(后置通知)、Interception Around Advice(周围通知)、Throws Advice(异常通知)和 Introduction Advice(引介通知)。

    Spring AOP的增强类型
    首先先了解一下增强接口的继承关系:

    下面分别进行介绍。

    如上图所示:
    其中带Spring标志的是Spring定义的扩展增强接口
    其中带aopalliance标志的是AOP联盟所定义的接口
     
    按照增加在目标类方法连接点的位置可以将增强划分为以下五类:
    • 前置增强   (org.springframework.aop.BeforeAdvice)   表示在目标方法执行前来实施增强
    • 后置增强   (org.springframework.aop.AfterReturningAdvice)   表示在目标方法执行后来实施增强
    • 环绕增强   (org.aopalliance.intercept.MethodInterceptor)   表示在目标方法执行前后同时实施增强
    • 异常抛出增强   (org.springframework.aop.ThrowsAdvice)   表示在目标方法抛出异常后来实施增强
    • 引介增强   (org.springframework.aop.introductioninterceptor)   表示在目标类中添加一些新的方法和属性
    其中,引介增强是一种特殊的增强。他可以在目标类中添加属性和方法,通过拦截定义一个接口,让目标代理实现这个接口。他的连接点是类级别的,而前面的几种则是方法级别的。
    其中,环绕增强是AOP联盟定义的接口,其他四种增强接口则是Spring定义的接口。
     
    其实,AOP增强很简单:
    通过实现这些增强接口,在实现这些接口的方法当中定义横切逻辑,然后通过配置Spring的配置文件就可以完成将增强织入到目标方法当中了。
     
    补充:增强既包含了横切逻辑同时又包含了部分连接点信息。
     

    前置增强:

    import org.springframework.aop.BeforeAdvice;
    import org.springframework.aop.MethodBeforeAdvice;
    import org.springframework.aop.framework.ProxyFactory;
    
    import java.lang.reflect.Method;
    
    public class Main{
        public static void main(String[] args) {
            //1、不使用xml配置实例化
            Worker target=new DigWorker();
            BeforeAdvice advice=new WearingBeforeAdvice();
            //Spring提供的代理工厂
            ProxyFactory pFactory=new ProxyFactory();
    //        //指定做优化,又将使用cglib动态
    //        pFactory.setOptimize(true);
    //
    //        //指定对接口进行代理,通过JDK动态代理
    //        pFactory.setInterfaces(target.getClass().getInterfaces());
    
            //设置代理目标,默认使用Cglib动态代理
            pFactory.setTarget(target);
    
            //为代理目标添加前置增强,这里会为目标的每个方法都增加增强
            pFactory.addAdvice(advice);
            //生成代理实例
            Worker proxy=(Worker)pFactory.getProxy();
            proxy.getTool("钻机");
            proxy.digSomething("煤炭");
            proxy.initWork();
        }
    }
    
    interface Worker {
        void getTool(String tool);
        void digSomething(String type);
        void initWork();
    }
    
    class DigWorker implements Worker{
    
        @Override
        public void getTool(String tool) {
            System.out.println("---------------调用方法--------------");
            System.out.println("领取工具:"+tool);
            // throw new RuntimeException("运行异常");
        }
    
        @Override
        public void digSomething(String type) {
            System.out.println("---------------调用方法--------------");
            System.out.println("开始卖力挖取:"+type);
    
        }
    
        @Override
        public void initWork() {
            System.out.println("生成一个DigWorker实例");
        }
    }
    
    class WearingBeforeAdvice implements MethodBeforeAdvice {
        public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
           if(arg1.length>0) {
               String thing = (String) arg1[0];
               System.out.println("--------------进行前置增强---------------");
               System.out.println("得到" + thing + "之前先穿上工作服!!");
           }else{
               System.out.println("--------------进行前置增强2---------------");
           }
        }
    }
    --------------进行前置增强---------------
    得到钻机之前先穿上工作服!!
    ---------------调用方法--------------
    领取工具:钻机
    --------------进行前置增强---------------
    得到煤炭之前先穿上工作服!!
    ---------------调用方法--------------
    开始卖力挖取:煤炭
    --------------进行前置增强2---------------
    生成一个DigWorker实例

    前置和后置:

    import org.springframework.aop.AfterReturningAdvice;
    import org.springframework.aop.MethodBeforeAdvice;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import java.lang.reflect.Method;
    
    public class Main{
        public static void main(String[] args) {
            //2、下面使用Spring的xml配置实例化
            ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
            //worker1带前置和后置增强
            Worker worker1=(Worker)ctx.getBean("worker1");
            System.out.println("worker1进入工作:");
            worker1.getTool("锄头");
        }
    }
    
    interface Worker {
        void getTool(String tool);
        void digSomething(String type);
        void initWork();
    }
    
    class DigWorker implements Worker{
    
        @Override
        public void getTool(String tool) {
            System.out.println("---------------调用方法--------------");
            System.out.println("领取工具:"+tool);
            // throw new RuntimeException("运行异常");
        }
    
        @Override
        public void digSomething(String type) {
            System.out.println("---------------调用方法--------------");
            System.out.println("开始卖力挖取:"+type);
    
        }
    
        @Override
        public void initWork() {
            System.out.println("生成一个DigWorker实例");
        }
    }
    
    class WearingBeforeAdvice implements MethodBeforeAdvice {
        public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
           if(arg1.length>0) {
               String thing = (String) arg1[0];
               System.out.println("--------------进行前置增强---------------");
               System.out.println("得到" + thing + "之前先穿上工作服!!");
           }else{
               System.out.println("--------------进行前置增强2---------------");
           }
        }
    }
    
    class WeaningAfterAdvice implements AfterReturningAdvice {
        @Override
        public void afterReturning(Object arg0, Method arg1, Object[] arg2,
                                   Object arg3) throws Throwable {
            System.out.println("--------------进行后置增强---------------");
            System.out.println("工作结束,请先脱掉工作服");
        }
    }

    benas文件:

    <?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:p="http://www.springframework.org/schema/p"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
        <!-- 要进行增强的目标 -->
        <bean id="target" class="com.company.DigWorker" init-method="initWork"/>
    
        <!-- 前置增强的方法 -->
        <bean id="beforeAdvice" class="com.company.WearingBeforeAdvice" />
        <!-- 后置增强的方法 -->
        <bean id="afterAdvice" class="com.company.WeaningAfterAdvice" />
    
        <!--同时设置前置增强和后置增强方法  -->
        <bean id="worker1" class="org.springframework.aop.framework.ProxyFactoryBean"
              p:proxyInterfaces="com.company.Worker" p:interceptorNames="beforeAdvice,afterAdvice"
              p:target-ref="target" lazy-init="true"/>
    </beans>

    Result:

    生成一个DigWorker实例
    worker1进入工作:
    --------------进行前置增强---------------
    得到锄头之前先穿上工作服!!
    ---------------调用方法--------------
    领取工具:锄头
    --------------进行后置增强---------------
    工作结束,请先脱掉工作服

    环绕增强:

    import org.aopalliance.intercept.MethodInvocation;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.aopalliance.intercept.MethodInterceptor;
    
    
    public class Main{
        public static void main(String[] args) {
            //2、下面使用Spring的xml配置实例化
            ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
            //work2带环绕增强
            Worker worker2=(Worker)ctx.getBean("worker2");
            System.out.println("worker2进入工作:");
            worker2.getTool("钻机");
        }
    }
    
    interface Worker {
        void getTool(String tool);
        void digSomething(String type);
        void initWork();
    }
    
    class DigWorker implements Worker{
    
        @Override
        public void getTool(String tool) {
            System.out.println("---------------调用方法--------------");
            System.out.println("领取工具:"+tool);
            // throw new RuntimeException("运行异常");
        }
    
        @Override
        public void digSomething(String type) {
            System.out.println("---------------调用方法--------------");
            System.out.println("开始卖力挖取:"+type);
    
        }
    
        @Override
        public void initWork() {
            System.out.println("生成一个DigWorker实例");
        }
    }
    
    class WearingInterceptor implements MethodInterceptor{
        @Override
        public Object invoke(MethodInvocation arg0) throws Throwable {
            Object[] args=arg0.getArguments();//目标方法入参
            String toolname=(String)args[0];
            System.out.println("--------------环绕增强开始---------------");
            System.out.println("得到"+toolname+"之前先穿上工作服");
            Object object=arg0.proceed();
            System.out.println("工作结束,请先脱掉工作服");
            System.out.println("--------------环绕增强结束---------------");
            return object;
        }
    }

    beans.xml

    <?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:p="http://www.springframework.org/schema/p"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
        <!-- 要进行增强的目标 -->
        <bean id="target" class="com.company.DigWorker" init-method="initWork"/>
        <!-- 环绕增强的方法 -->
        <bean id="aroundAdvice" class="com.company.WearingInterceptor" />
        <!--设置环绕增强方法  -->
        <bean id="worker2" class="org.springframework.aop.framework.ProxyFactoryBean"
              p:proxyInterfaces="com.company.Worker" p:interceptorNames="aroundAdvice"
              p:target-ref="target" lazy-init="true"/>
    </beans>

    Result:

    生成一个DigWorker实例
    worker2进入工作:
    --------------环绕增强开始---------------
    得到钻机之前先穿上工作服
    ---------------调用方法--------------
    领取工具:钻机
    工作结束,请先脱掉工作服
    --------------环绕增强结束---------------

    异常抛出增强:

    import org.springframework.aop.ThrowsAdvice;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import java.lang.reflect.Method;
    
    public class Main{
        public static void main(String[] args) throws Exception {
            //2、下面使用Spring的xml配置实例化
            ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
            //work3带环绕增强
            Worker worker3=(Worker)ctx.getBean("worker3");
            System.out.println("worker3进入工作:");
            worker3.getTool("锤子");
        }
    }
    
    interface Worker {
        void getTool(String tool);
        void digSomething(String type);
        void initWork();
    }
    
    class DigWorker implements Worker{
    
        @Override
        public void getTool(String tool) {
            System.out.println("---------------调用方法--------------");
            System.out.println("领取工具:"+tool);
            throw new RuntimeException("运行异常");
        }
    
        @Override
        public void digSomething(String type) {
            System.out.println("---------------调用方法--------------");
            System.out.println("开始卖力挖取:"+type);
    
        }
    
        @Override
        public void initWork() {
            System.out.println("生成一个DigWorker实例");
        }
    }
    
    
    class WeaningThrowAdvice implements ThrowsAdvice {
        public void afterThrowing(Method method, Object[] args, Object target, Exception ex) throws Throwable {
            System.out.println("--------------------");
            System.out.println("method:"+method.getName());
            System.out.println("抛出异常"+ex.getMessage());
            System.out.println("成功回滚事务");
        }
    }

    beans.xml

    <?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:p="http://www.springframework.org/schema/p"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
        <!-- 要进行增强的目标 -->
        <bean id="target" class="com.company.DigWorker" init-method="initWork"/>
    
        <!-- 异常抛出增强的方法  -->
        <bean id="throwAdvice" class="com.company.WeaningThrowAdvice" />
    
        <!--设置异常抛出增强方法  proxyTargetClass="true",使用CgLib代理-->
        <bean id="worker3" class="org.springframework.aop.framework.ProxyFactoryBean"
              p:interceptorNames="throwAdvice"
              p:target-ref="target"
              p:proxyTargetClass="true"/>
    </beans>

    Result:

    生成一个DigWorker实例
    worker3进入工作:
    ---------------调用方法--------------
    领取工具:锤子
    Exception in thread "main" java.lang.reflect.UndeclaredThrowableException
        at com.company.DigWorker$$EnhancerBySpringCGLIB$$b3caca85.getTool(<generated>)
        at com.company.Main.main(Main.java:18)
        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 com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
    Caused by: java.lang.IllegalAccessException: Class org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor can not access a member of class com.company.WeaningThrowAdvice with modifiers "public"
        at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
        at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
        at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
        at java.lang.reflect.Method.invoke(Method.java:491)
        at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor.invokeHandlerMethod(ThrowsAdviceInterceptor.java:145)
        at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor.invoke(ThrowsAdviceInterceptor.java:130)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:656)

    http://blog.csdn.net/icarus_wang/article/details/51737474

    http://www.kancloud.cn/evankaka/springlearning/119668

  • 相关阅读:
    机房收费系统重构(三)—工厂+反射+DAL
    机房收费系统重构(二)—菜鸟入门
    机房收费系统重构(—)—小试牛刀
    vb.net机房收费登录功能
    设计模式总结之结构型模式
    设计模式总结之创建型模式
    大话设计之桥接模式
    大话设计之单例模式
    大话设计之适配器模式
    大话设计之抽象工厂模式
  • 原文地址:https://www.cnblogs.com/hongdada/p/6510314.html
Copyright © 2020-2023  润新知