精华内容
下载资源
问答
  • 当然,这个方法也要改,它是有返回值的,它的返回值是 Object 类型,要不然,你还是会被环绕通知的切面类里面的方法拦截的 当然了,代码写完了,配置文件还是要配置的... 在配置再来个 <bean> 标签 再来个 ...

    首先让我们先说一下切面需要我们关注哪些地方(组成部分),

    1.切面点表达式[pointcut]:指定类的指定方法(就是为了定位指定类的指定方法)

    2.方位:定义在指定方法的前,后,抛出异常,等等

    3.执行横切业务逻辑:公共部分的代码,

    注:那什么是公共部分的代码?如:日志记录,性能统计,安全控制,事务处理等方面

    4.通知[advice] : 包涵方位,横切业务逻辑

    5.连接点[JoinPoint] : 包涵切点表达式,方位

     

    什么意思那??一张图告诉你,,,

    接着我们要知道一个常识 ;

    我们AOP可以实现的功能不用AOP也可以实现

     

    那问题来了,我们不用AOP怎么实现这个日志的记录

    那我们就举个Product的栗子:

    比如写增加时(伪代码)

    addProduct(){
    
        log.info("开始执行addProduct方法")
    
        添加产品的核心逻辑
    
        log.error("执行出错:某某某")
    
    }

    那删除也是一样的

    deleteProduct(){
    
        log.info("开始执行deleteProduct方法")
    
        添加产品的核心逻辑
    
        log.error("执行出错:某某某")
    
    }

     

    之后的修改也一样,,,

    那,问题来了,这样写方便吗???

    是,现在写,感觉挺方便,但是有没有考虑到一个问题,

    这是在写一个的增删改,那么我们在正常的项目里,有多少条增删改,,,

    1百?一千?1一万???

    那你就按1千算,1000×(3+2)=6000行代码

    你这样就莫名其妙的写了6000行或者说N行代码,

    你不会用AOP时,你又要必须写和用,你就得这样写

    ......

    程序猿开发效率,代码冗余的问题,这都是很严重的问题

    所以说,怎么解决现在这些非核心业务逻辑的代码,

    那就用到切面...

    那,一句话怎么总结这个切面,

    在指定类的指定方法的前后进行特定的业务逻辑

    为什么使用这个切面:

    还是刚刚说的,为了将代码中的非核心代码提取出来,进行统一的处理,从而提高开发效率,让程序猿只需要关心核心业务逻辑代码

    之后我们会说一说如何实现一个基本的前置通知与后置通知,让大家先了解了解

     

    前置通知:

    首先我们说说前置通知,

    先来的简单的要求,要求:

    在controller层的每个类的每个方法之前,打印出 '你好Java' 在说之前那我要强调的是,大家要知道,能用注解完成的,都可以用配置文件来完成,相反,用配置文件完成的也可以用注解来完成,

    我就不用注解了,用注解的方式来完成

    1、首先我们先建一个新的class文件,我的就叫 FHspect

    2、直接输出 你好java

    现在就写好了,就差配置它了,如果我不配置它,它就是一个普通的java类,如果我给它配置好,它就被称为切面类而不是普通的java类,这个类 叫 '切面类' ,这个方法就叫 '横切业务逻辑'

    3、在spring-controller.cml里配置如下

    我一一给大家解释,

    ①首先是 <bean> 标签里的 class 的路径,指向的是我们刚刚写的 class 类

    ②而 <bean> 标签的 id 指向的是下面的 <aop:config> 标签里面的 <aop:aspect> 标签下的 ref 的名称保持一致

    ③<aop:pointcut> 里的 expression 的意思是表达式的意思,那后面的是 execution(* 路径),而括号里的内容是说,这个路径下的controller下的,任意嵌套的子包 下的 任意 类 下的 任意 方法 ,而括号中的意思是代表 任意类型的参数

    ④<aop:pointcut> 标签里的 id 与 <aop:before> 标签里的 pointcut-ref 的名称保持一致

    ⑤要知道 <aop:pointcut> 标签代表的意思是方位 ,它里面的 method 跟的是你要执行的方法名

    总结: 在这些 com.fh.shop.controller..*.*(..) 方法的前面执行 com.fh.shop.aspect.FHAspect 这个切面类中的 showInfo 的方法.

    注: <aop:pointcut ref="fh123"> = com.fh.shop.aspect.FHAspect <aop:before> 标签里的 method = showInfo

    这样就配置好了,那接下来就可以看效果了,,, ,,,

    成功输出...

     

    后置通知:

    还是,再来说一个要求:

    在controller层的每个类的每个方法之前/后,打印出 '你好Java_方法名()'

    还是写一个普通的方法,

    public void showInfo(JoinPoint jp){
        System.out.println("你好JAVA");
    }

    那怎么怎么获取方法名

    public void showInfo(JoinPoint jp){
        String methodName = jp.getSignature.getName();
        System.out.println("你好JAVA");
    }

    注: getSignature 代表的是方法的签名,而 getName 代表的是方法名

    最终的样子是如下的

    //之前
    public void showInfo(JoinPoint jp){
        String methodName = jp.getSignature.getName();
        System.out.println("前置:你好JAVA"+methodName +"()");
    }
    //之后
    public void doInfo(JoinPoint jp){
        String methodName = jp.getSignature.getName();
        System.out.println("后置:你好JAVA"+methodName +"()");
    }

    这只是写完了一个普通方法,还是和刚刚一样,要去配置

    在刚刚的配置后加上

    <aop:after method="doInfo" pointcut-ref="fhPointCut">

    实际效果如下:

    这就好了,,,你就可以看看效果了

     

    环绕通知

    首先我们肯定是先要有一个类

    我的就叫LogAspect

    然后我需要导入相关的jar包了,

     

    好了我的jar包也导入了然后我们就要该配置文件了,这总要有log4j来做为支持

    log4j是放到resources文件夹下即可

    我们一般项目上线后将log4j设置为 INFO 级别或比 INFO 级别更高的级别, debug 级别的太多了,所以一般不用,当然在开发的时候,当然随便了...

    我们先设置成DeBug级别试一下 然后我们就启动,并访问以下,看它与正常情况下有什么区别,

    就如你看到的一样,会将你执行的出你所用到的 SQL 语句,但是!!!毕竟 Debug打出来的数据太庞大了,大部分又不用,设置成 INFO 级别又不给打印 sql 语句,那我们就需要在log4j里配置一下了

    log4j.rootLogger=info,名

    log4j.logger.路径=debug

    实际如下:

    这两行的意思分别说说,

    首先是第一行,log4j.rootLogger=info,名:

    这是说,其他包下的(非项目中的包下的)都设置成 INFO 级别,

    然后是第二行,log4j.logger.路径=debug:

    只要是我这个项目路径下的全部都设置成 debug 级别

    记住!现在是debug,是方便你做修改,但是!!!项目上线后,切记切记要将两个都改为INFO级别,或INFO更高的级别!!!

    然后我们就要对所有的日志进行统一的处理,找到我们刚刚建的 LogAspect

    我们就要先声明一个 log 的日志类

    private static final Logger LOG = LoggerFactory.getLogger(LogAspect.class);

     

    注:要注意的是Logger 用的是 org.slf4j 资源包,因为 slf 公司对 log 的资源做了封装,知道就行了...

    接下来写一个 doLog 的普通方法,额,等等..

    我们先要思考一个东西, 要知道,我们最后的要求是在控制台打印出:

    执行XX类.方法名() 花费了XXX时间

    执行XX类.方法名()报错:错误为XXX

    好了,知道了要求,我们就可以用环绕通知了 ProceedingJoinPoint 实际代码为:

    然后我们首先获取类名:

    然后是方法名:

    然后打印出来

    打印有两种方式:

    LOG.info("执行"+canonicalName+"类名为:"+methodName)

    或者

    LOG.info("执行{}类{}方法()",canonicalName, methodName)

    注:这是用大括号当做占位符,然后用后面的别名替换占位符,小括号还是小括号

    这些还是不够的,这样就需要讲到另一个东西了,

    如果只有上面的这些代码,你是不能跳转,最后你跳转的结构是404,还需要写一个东西,

    Object result = pjp.proceed()

    还要捕获一下,而这句话的意思是:执行真正的业务逻辑

    什么叫执行真正的业务逻辑?你可以理解为,执行了就不会出现刚刚的404

    但是,光这样你还是会被环绕通知给拦截掉,所以,还要返回 result

    在最上面先声明一个全局变量,再在下面返回 result

    完整代码如下:

    当然,这个方法也要改,它是有返回值的,它的返回值是 Object 类型,要不然,你还是会被环绕通知的切面类里面的方法拦截的

    当然了,代码写完了,配置文件还是要配置的...

    在配置再来个 <bean> 标签

    再来个 <aop:aspect> 标签,你的 <aop:aspect> 标签可以写在之前的 <aop:config> 里面,然后...

    后面的被遮住的 id 还是与 pointcut-ref 保持一致

    然后就写完了,你就可以访问页面来看看效果了...

    之后我们还要加一些东西,花费的时间,

    在执行方法之前加如下内容,

    这意思是:记录当前时间

    然后在执行完后,再写一个:

    意思是:记录结束时间

    最后,在之前的info里面再加个如下内容:

    而这个end-start是说:用最后的结束时间,减去开始时记录的时间最后等于中间执行一共花费的时间

    注:两个所记录的时间最小到毫秒值,所以,最后减出来的也是到毫秒值

    实际代码如下:

    那,出现异常了又改怎么办?

    还是和刚刚的一样也是写一个

    那我们对于异常的处理,都是往外抛

    最后整体的代码如下:

    最后我们执行出来的效果也有了:

    错误的打印我也有

    错误级别就是error级别,因为我们给的级别比较低,是 debug 级别,所以只要比debug级别高的都会显示,哪怕我们最后项目上线,我们把级别改成 INFO 级别的,但是它还是会在控制台打印出 INFO 级别和 error 级别

    在这里那我就说一下我们最常用几个级别,最常用的不是所有,

    error>warn>info>debug

    就行了....

    展开全文
  • NULL 博文链接:https://z18022893621.iteye.com/blog/1956146
  • Spring aop 前置、后置环绕通知详解

    千次阅读 2019-01-03 14:02:42
    代理模式实现前置通知、后置通知和环绕通知。 代理目标接口: package com.print; public interface IPrinter {  public String print(String content); } 代理目标类: package com.print.impl; import ...

    代理模式实现前置通知、后置通知和环绕通知。

    代理目标接口:

    package com.print;

    public interface IPrinter {

       public String print(String content);

    }

    代理目标类:

    package com.print.impl;

    import com.print.IPrinter;

    public class Printer implements IPrinter {

       public String print(String content) {

          System.out.println(输出内容:["+content+"]");

          return content;

       }

    }

    • 前置通知:

    切面类:

    package com.print.advices;

    import java.lang.reflect.Method;

    import org.springframework.aop.MethodBeforeAdvice;

    public class MyBeforAdvice implements MethodBeforeAdvice {

       /**

        * @param m 被通知的方法对象,args 被通知的方法的参数,taget 被代理的没标类对象

        */

       public void before(Method m, Object[] args, Object taget)

            throws Throwable {

          System.out.println("前置通知开始:--------------");

          System.out.println("方法名:"+m.getName());

          System.out.println("参数列表长度:"+args.length);

          System.out.println("参数:");

          for(Object a : args){

            System.out.println("\t"+a.toString());

          }

          System.out.println("对象名:"+taget.getClass().getName());

          System.out.println("前置通知结束-----------------");

       }

    }

    Spring配置:

    <!--前置通知切面bean -->

       <bean id="beforAdvice" class="com.etp.zsh.MyBeforeAdvice"/>

       <!-- 代理目标bean -->

       <bean id="taget" class="com.print.impl.Printer"/>

       <!-- 代理bean -->

       <bean id="printer" class="org.springframework.aop.framework.ProxyFactoryBean">

          <!-- 注入属性代理目标接口 -->

          <property name="proxyInterfaces" value="com.print.IPrinter "/>

          <!-- 注入属性代理目标bean -->

          <property name="target" ref="taget"/>

          <!-- 注入属性切面bean -->

          <property name="interceptorNames">

            <list>

               <value>beforAdvice</value>

            </list>

          </property>

       </bean>

    测试类:

    package com.print.test;

    import org.springframework.context.ApplicationContext;

    import org.springframework.context.support.FileSystemXmlApplicationContext;

    import com.print.IPrinter;

    public class Test {

       public static void main(String[] args) {

          ApplicationContext context = new FileSystemXmlApplicationContext("/src/applicationContext.xml");

          IPrinter colorPrinter = (IPrinter)context.getBean("printer");

          colorPrinter.print("do something");

       }

    }

    输出结果:

    前置通知开始:--------------

    方法名:print

    参数列表长度:1

    参数:

       do something

    对象名:com.print.impl.Printer

    前置通知结束----------------

    输出内容:[do something]

     

    • 后置通知:

    依然使用上边的目标类

    后置通知切面类:

    package com.print.advices;

    import java.lang.reflect.Method;

    import org.springframework.aop.AfterReturningAdvice;

    public class MyAfterReturnAdvice implements AfterReturningAdvice {

           /**

            * @param returnObj 被通知方法的返回值, m 被通知的方法对象,args 被通知的方法的参数,taget 被代理的没标类对象

            */

           public void afterReturning(Object returnObj, Method m, Object[] args,

                         Object taget) throws Throwable {

                  System.out.println("后置通知开始:--------------");

                  System.out.println("方法返回值:"+ returnObj);

                  System.out.println("方法名:"+m.getName());

                  System.out.println("参数列表长度:"+args.length);

                  System.out.println("参数:");

                  for(Object a : args){

                         System.out.println("\t"+a.toString());

                  }

                  System.out.println("对象名:"+taget.getClass().getName());

                  System.out.println("后置通知结束----------------");

           }

    }

    applicationContext.xml中添加后置通知切面bean配置:

    <!-- 后置通知切面 -->

       <bean id="arterReturnAdvice" class="com.print.advices.MyAfterReturnAdvice"/>

    在代理bean中添加切面arterReturnAdvice:

    <property name="interceptorNames">

            <list>

               <value>beforAdvice</value>

               <value>arterReturnAdvice</value>

            </list>

          </property>

    运行测试,得到结果:

    前置通知开始:--------------

    方法名:print

    参数列表长度:1

    参数:

       do something

    对象名:com.print.impl.Printer

    前置通知结束----------------

    输出内容:[do something]

    后置通知开始:--------------

    方法返回值:do something

    方法名:print

    参数列表长度:1

    参数:

       do something

    对象名:com.print.impl.Printer

    后置通知结束----------------

     

    三、环绕通知:

    依然使用上边的目标类

    环绕通知切面类:

    package com.print.advices;

    import org.aopalliance.intercept.MethodInterceptor;

    import org.aopalliance.intercept.MethodInvocation;

    public class MyInterceptor implements MethodInterceptor {

           /**

            * @param invocation 被代理的目标对象

            */

           public Object invoke(MethodInvocation invocation) throws Throwable {

                  Object returnObj = null;

                  System.out.println("{{{{{{环绕通知开始}}}}}}");

                  //执行代理目标的被通知的方法

                  returnObj = invocation.proceed();

                  System.out.println("{{{{{{环绕通知结束}}}}}}");

                  return returnObj;

           }

    }

    applicationContext.xml中添加环绕通知切面bean配置:

    <!-- 环绕通知切面 -->

       <bean id="myInterceptor" class="com.print.advices.MyInterceptor"/>

    在代理bean中添加切面myInterceptor:

    <property name="interceptorNames">

            <list>

               <value>beforAdvice</value>

               <value>arterReturnAdvice</value>

    <value>myInterceptor</value>

            </list>

          </property>

    运行测试,得到结果:

    前置通知开始:--------------

    方法名:print

    参数列表长度:1

    参数:

       do something

    对象名:com.print.impl.Printer

    前置通知结束----------------

    {{{{{{环绕通知开始}}}}}}

    输出内容:[do something]

    {{{{{{环绕通知结束}}}}}}

    后置通知开始:--------------

    方法返回值:do something

    方法名:print

    参数列表长度:1

    参数:

       do something

    对象名:com.print.impl.Printer

    后置通知结束----------------

     

    展开全文
  • spring的几个通知(前置、后置环绕、异常、最终)

    spring的几个通知(前置、后置、环绕、异常、最终)

    参考文章:

    (1)spring的几个通知(前置、后置、环绕、异常、最终)

    (2)https://www.cnblogs.com/xiaostudy/p/9535857.html


    备忘一下。


    展开全文
  • target:目标对象 (Object) 前置通知(org.springframework.aop.MethodBeforeAdvice):在连接点之前执行的通知() 后置通知(org.springframework.aop.AfterReturningAdvice):在连接点正常完成后执行的通知 环绕通知...

    一,AOP中关键性概念

    ①、连接点(Joinpoint):程序执行过程中明确的点,如方法的调用,或者异常的抛出,

    ②、目标(Target):被通知(被代理)的对象
     注1:完成具体的业务逻辑

    ③、通知(Advice):在某个特定的连接点上执行的动作,同时Advice也是程序代码的具体实现,例         如一个实现日志记录的代码(通知有些书上也称为处理)
     注2:完成切面编程

    ④、代理(Proxy):将通知应用到目标对象后创建的对象(代理=目标+通知),
           例子:外科医生+护士
    注3:只有代理对象才有AOP功能,而AOP的代码是写在通知的方法里面的

    ⑤、切入点(Pointcut):多个连接点的集合,定义了通知应该应用到那些连接点。
          (也将Pointcut理解成一个条件 ,此条件决定了容器在什么情况下将通知和目标组合成代理返          回给外部程序)

    ⑥、适配器(Advisor):适配器=通知(Advice)+切入点(Pointcut)

    如何实现AOP

    ①、目标对象只负责业务逻辑代码;

    ②、通知对象负责AOP代码,这二个对象都没有AOP的功能,只有代理对象才有;

    AOP:即面向切面编程

    AOP带来的好处:让我们可以 “专心做事”

    工具类org.springframework.aop.framework.ProxyFactoryBean用来创建一个代理对象,在一般         情况下它需要注入以下三个属性:
                  proxyInterfaces:代理应该实现的接口列表(List)
                  interceptorNames:需要应用到目标对象上的通知Bean的名字。(List)
                  target:目标对象 (Object)

    前置通知(org.springframework.aop.MethodBeforeAdvice):在连接点之前执行的通知()

    后置通知(org.springframework.aop.AfterReturningAdvice):在连接点正常完成后执行的通知

    环绕通知(org.aopalliance.intercept.MethodInterceptor):包围一个连接点的通知,最大特点是可以修改返回值,由于它在方法前后都加入了自己的逻辑代码,因此功能异常强大。
    它通过MethodInvocation.proceed()来调用目标方法(甚至可以不调用,这样目标方法就不会执 行)

    异常通知(org.springframework.aop.ThrowsAdvice):这个通知会在方法抛出异常退出时执行

    适配器(org.springframework.aop.support.RegexpMethodPointcutAdvisor) 适配器=通知                  (Advice)+切入点(Pointcut)
     

    二,前置通知

    1.新建接口 interface IBookBiz,定义方法

    package com.ltf.aop.biz;

    public interface IBookBiz {
        // 购书
            public boolean buy(String userName, String bookName, Double price);

            // 发表书评
            public void comment(String userName, String comments);
    }
     

     2.(业务代码)实现类BookBizImpl implements IBookBiz实现接口,并重写方法

    package com.ltf.aop.biz.impl;

    import com.ltf.aop.biz.IBookBiz;
    import com.ltf.aop.exception.PriceException;

    public class BookBizImpl implements IBookBiz {
        public BookBizImpl() {
            super();
        }

        public boolean buy(String userName, String bookName, Double price) {
            // 通过控制台的输出方式模拟购书
            if (null == price || price <= 0) {
                throw new PriceException("book price exception");
            }
            System.out.println(userName + " buy " + bookName + ", spend " + price);
            return true;
        }

        public void comment(String userName, String comments) {
            // 通过控制台的输出方式模拟发表书评
            System.out.println(userName + " say:" + comments);
        }
    }
     

    3.前置通知MyMethodBeforeAdvice 类 implements MethodBeforeAdvice(实现验证的功能)

    (如果只有代码没有implements MethodBeforeAdvice 会报最后文章一张图的错误)

    package com.ltf.aop.advice;

    import java.lang.reflect.Method;
    import java.util.Arrays;

    import org.springframework.aop.MethodBeforeAdvice;

    public class MyMethodBeforeAdvice implements MethodBeforeAdvice{

    /**
     * 前置通知(验证)
     * @param method
     * @param arg1
     * @param target
     * @throws Throwable
     */
        public void before(Method method, Object[] arg1, Object target) throws Throwable {
            String clzName = target.getClass().getName();
            String MethodName = method.getName();
            String params = Arrays.toString(arg1);
            System.out.println("买书评论前加系统日志:"+clzName+"."+MethodName+"("+params+")");
        }

    }
     

    target:目标对象

    method:被触发的目标对象的方法

    arg1:目标对象的目标方法携带的参数

    4,配置

    在spring-context.xml中,配置目标

        <!-- 目标 -->
        <bean name="bookBiz" class="com.ltf.aop.biz.impl.BookBizImpl"></bean>

    获取bookBiz,运行输出

    IBookBiz iBookBiz = (IBookBiz) applicationContext.getBean("bookBiz");

     运行只是输出,但是没有验证

    因此我们需要调用MyMethodBeforeAdvice里面的方法

    首先我们要在spring-context.xml中,配置前置通知

        <!-- 前置通知 -->
        <bean name="myBefore" class="com.ltf.aop.advice.MyMethodBeforeAdvice"></bean>

    再配置 ,生成代理对象 (目标+通知)

        <!-- 生成代理对象 (目标+通知) -->
        <bean class="org.springframework.aop.framework.ProxyFactoryBean"
            id="proxyFactoryBean">
            <property name="target" ref="bookBiz"></property>
            <!-- 代理工厂生产的代理需要实现的接口列表 -->
            <property name="proxyInterfaces">
                <list>
                    <value>com.ltf.aop.biz.IBookBiz</value>
                </list>
            </property>
            <property name="interceptorNames">
            <list>
            <value>myBefore</value>
            </list>
            </property>
        </bean>

    ref为目标

    value为代理工厂生产的代理需要实现的接口列表,也是这里的目标的接口 

    获取proxyFactoryBean,运行输出

    IBookBiz iBookBiz = (IBookBiz) applicationContext.getBean("proxyFactoryBean");

     运行结果说明每一个常规业务代码的执行都调用了前置通知,并表明调用了什么方法,携带了什么参数

    前置通知的价值在于:创建session,开启事务 

    三,后置通知

    1.后置通知代码类(MyAfterRetruningAdvice implements AfterReturningAdvice

    package com.ltf.aop.advice;

    import java.lang.reflect.Method;
    import java.util.Arrays;

    import org.springframework.aop.AfterReturningAdvice;

    public class MyAfterRetruningAdvice implements AfterReturningAdvice{
        
        @Override
        public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
            String clzName = target.getClass().getName();
            String MethodName = method.getName();
            String params = Arrays.toString(args);
            System.out.println("后置通知:"+clzName+"."+MethodName+"("+params+")"+"返回:"+returnValue);
        }
     
    }
     

    2,在spring-context.xml中,配置后置通知

         <!-- 后置通知 -->
        <bean name="myAfter" class="com.ltf.aop.advice.MyAfterRetruningAdvice"></bean>

     因为目标对象相同,所以写在同一个list里面

            <list>
            <value>myBefore</value>
            <value>myAfter</value>
            </list>

     3,运行结果如下

    前置通知----》目标对象的业务代码----》后置通知 

     boolean  返回类型true

    void   返回类型null

     后置通知价值在于:速度提交,关闭session

    四,环绕通知

    1.环绕通知代码(MyMethodInterceptor implements MethodInterceptor

    package com.ltf.aop.advice;

    import java.lang.reflect.Method;
    import java.util.Arrays;

    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;

    public class MyMethodInterceptor implements MethodInterceptor{

        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            Object target = invocation.getThis();
            Method method = invocation.getMethod();
            Object[] args = invocation.getArguments();
            String targetName = target.getClass().getName();
            String methodName = method.getName();
            String params = Arrays.toString(args);
            System.out.println("环绕通知:调用---"+targetName+"的方法---"+methodName+"  参数为--"+params);
            Object returnValue = invocation.proceed();
            System.out.println("环绕通知:目标对象所调用的方法的返回值:"+returnValue);
            return returnValue;
        }

    }
     

    invocation:

    其一:通过这一个参数可以获取到标对象、被触发的目标对象的方法、目标对象的目标

    方法的携带的参数、返回值这四个参数;

     其二:通过这行代码Object returnValue = invocation.proceed();(实际调用的时bookdao的buy方法)

    invocation可以执行被代理的目标对象的业务方法(相当于过滤器    chain.dofilter:放行)

    2,在spring-context.xml中,配置环绕通知

          <!-- 环绕通知 -->
            <bean name="myInterceptor" class="com.ltf.aop.advice.MyMethodInterceptor">      </bean>
     

         <value>myInterceptor</value>

    3,运行结果

    相当于调用业务代码,在前置通知后,后置通知前,产生两次

    环绕通知价值在于:包含了前置通知和后置通知 

    五,异常通知

    例如:加入订单插入失败,订单项肯定是不能插入的(要么同时成功,要么同时失败)

    所以说处理失败的业务逻辑代码,可以将数据进行回滚;

    异常通知一定要实现 ThrowsAdvice,且afterThrowing方法名不能修改;

    1.异常通知代码(MyThrowsAdvice implements ThrowsAdvice

    package com.ltf.aop.advice;

    import org.springframework.aop.ThrowsAdvice;

    import com.ltf.aop.exception.PriceException;


    public class MyThrowsAdvice implements ThrowsAdvice{

        public void afterThrowing(PriceException exception) {
            System.out.println("价格输入有误,购买失败,请重新输入");
        }
    }
     

    2,在spring-context.xml中,配置环绕通知

        <!-- 异常通知 -->
            <bean name="myException" class="com.ltf.aop.advice.MyThrowsAdvice"></bean>

        <value>myException</value>

    3,修改成错误价格运行如下

      异常通知的价值在于:处理异常数据,事务回滚

    六,过滤通知

    对应现实中的开发场景,假如有10张表,并不是所有的表都需要系统日志,因此需要过滤;

    在spring-context.xml中,配置过滤 通知

    org.springframework.aop.support.RegexpMethodPointcutAdvisor   这个类是固定的 myFiltermyFilter:过滤的是后置通知

        <!-- 过滤通知 -->
        <bean name="myFilter" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
            <property name="advice" ref="myAfter" />
            <property name="patterns">
                <list>
                    <value>.*buy</value>
                </list>
            </property>
        </bean>

     <list>
                    <value>myBefore</value>
                    <!-- <value>myAfter</value> -->
                    <value>myFilter</value>
                    <value>myInterceptor</value>
                    <value>myException</value>
                </list>

    运行结果如下

     只有买书有返利,评论没有返利

    复制全路径名的方法

    1.在左侧工具栏中选中,右键,点击Copy Qualified Name:

     /spring01/src/test/java/com/ltf/aop/biz/impl/BookBizImpl.java

     2,在类中如下图选中,右键,点击Copy Qualified Name:

    com.ltf.aop.biz.impl.BookBizImpl

    展开全文
  • 前置增强、后置增强、环绕增强听起来说实话,我完全不清楚是什么意思,研究以后,发现很简单,就是对方法的增强,比如前置增强,就是我有一个方法A,但是有一些功能是通用的,我不想写到A里面,但是A方法又需要使用...
  • 后置 @AfterReturning(value="@annotation(com.sdyy.biz.act.maint.aop.annotation.ResIfNull)",returning="result") public void AfterReturning(JoinPoint joinPoint , Object result) { logger.in...
  • TestServiceInter2.java 测试类:Test1Service.java实现了上述两个接口 前置通知类:MyMethodBeforeAdvice.java 后置通知类:MyAfterReturningAdvice.java 环绕通知类:MyMethodInterceptor.java 异常通知类:...
  • 1.新建切入点 2.配置切面 3.applicationContext.xml 环绕通知可以包含其他通知,根据自己需求来 访问入口:
  • result是方法的返回值 //result就是目标方法addStudent()方法的返回值 //invocation.proceed()后面的代码是后置通知 System.out.println("用环绕通知实现的后置通知"); /* * 通过invocation获取之前...
  • Spring的aspectj的AOP操作(前置增强 后置增强 环绕通知)  bean3.xml 配置文件 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www
  • System.out.println("环绕-后置"); return result; } } 测试 传参 aspectJ相比于schema-based,传参要麻烦很多 下面有一份前置通知,demo1方法有int和string两个参数 applicationContext.xml args(int id1,...
  • spring的Aop中的前置通知,后置通知以及环绕通知简单代码
  • 将前置通知后置通知与环绕通知类分开实现 前置加后置类 package com.zx.aop; import java.lang.reflect.Method; import org.springframework.aop.AfterReturningAdvice; import org.springframework.aop....
  • 环绕增强 package cjq.demo.spring.aop; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.springframework.stereotype.Component; ...
  • ①AOP的前置通知方法 、后置通知方法 、环绕通知方法 首先导入相关的包: (1)定义一个java文件来使用AOP技术。(LogAdvice.java(日志通知切面)) LogAdvice.java package com . advice ; import ...
  • //环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法 //且环绕通知必须有返回值,返回值即目标方法的返回值。 @Around("execution(public int ...
  • spring框架的五种通知...后置通知 在目标方法调用之后执行,一旦目标方法产生异常不会执行 aop:after 最终通知 在目标调用方法之后执行,无论目标方法是否产生异常,都会执行 aop:after-throwing 异常通知 当...
  •  System.out.println("后置通知:"+joinpoint.getSignature().getName()+"---->"+ret);  } //   @Around(value="mypoincut()")  public Object myaround(ProceedingJoinPoint joinpoint) throws Throwable{ ...
  • } // @AfterReturning(value="mypoincut()",returning="ret") public void myafterreturning(JoinPoint joinpoint,Object ret){ System.out.println("后置通知:"+joinpoint.getSignature().getName()+"---->"+ret...
  • } /** * 环绕通知,围绕着方法执行 * 环绕通知需要携带ProceedingJoinPoint类型的参数 * 环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法。 * 而且环绕通知必须有返回值,...
  • @Around:环绕通知,围绕着方法执行:环绕通知类似于动态代理全过程即综合了(前置、后置、返回、异常通知)为一体的通知: /** * 环绕通知:需要携带ProceedingJoinPoint 类型的参数 * 环绕通知类似于动态...
  • 设置前置通知,后置通知,返回通知,异常通知的方式 环绕通知配置 项目配置 新建一个包,并且将aop包下面的所有java文件全部拷过来 删除注解 删除红框中的所有注解   新建一个...
  • 定义通知 通知有五种类型,分别是: 前置通知(@Before):在目标方法调用之前调用通知 后置通知(@After):在目标方法完成之后调用通知 环绕通知(@Around):在被通知的方法调用之前和调用之后执行自定义的方法 ...
  • --在环绕通知中需要明确调用 ProceedingJoinPoint 的 proceed() 方法来执行被代理的方法. 如果忘记这样做就会导致通知被执行了, 但目标方法没有被执行. --注意: 环绕通知的方法需要返回目标方法执行之后的结果, 即...
  • 项目是springboot项目,通过springboot-aop,配置环绕通知,记录调用地址、入参、返回参数、ip,同时记录执行时间等,以便定位问题。具体的入库就是弄个表,保存下获取到的值,这里就不多做介绍了。 2.1 AOP简要说明...
  • } } 配置spring-context.xml 调用测试AopTest.java 运行结果如下 暗暗 四、环绕通知:包含前置+后置通知 环绕通知MythodInterceptor(要实现MethodInterceptor接口): package com.lgs.aop.advice; import java....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 25,242
精华内容 10,096
关键字:

后置环绕