• 简述spring中常有的几种advice?


    在Spring中,Advice都是通过Interceptor来实现的,主要有以下几种:

    1. 环绕Advice:

    //例子摘自Spring reference
    public interface MethodInterceptor extends Interceptor {
          Object invoke(MethodInvocation invocation) throws Throwable;
    }
    public class DebugInterceptor implements MethodInterceptor {
    
        public Object invoke(MethodInvocation invocation) throws Throwable {
            System.out.println("Before: invocation=[" + invocation + "]");  //(1)
            Object rval = invocation.proceed();
            System.out.println("Invocation returned");  //(2)
            return rval;
        }
    }

    环绕advice类似一个拦截器链,这个拦截器链的中心就是被拦截的方法。在程序(1)(2)我们可以加入我们自己的代码,以表示在方法执行前后我们需要干什么。invocation.proceed()方法运行指向连接点的拦截器链并返回proceed()的结果。

    2. Before Advice

    public interface MethodBeforeAdvice extends BeforeAdvice {
        void before(Method m, Object[] args, Object target) throws Throwable;
    }

     一个更简单的通知类型是before 通知。它不需要 MethodInvocation对象,因为它只是在进入方法之前被调用。before advice的一个主要优点是它不需要调用proceed()方法,因此就不会发生 无意间运行拦截器链失败的情况。

    3. After advice

    public interface AfterReturningAdvice extends Advice {
        void afterReturning(Object returnValue, Method m, Object[] args, Object target) throws Throwable;
    }
    !

    一个After advice可以访问返回值(但不能进行修改),被调用方法,方法参数以及目标对象。

    4.Throws Advice

    //ThrowsAdvice 是一个空接口,起标识作用
    public interface ThrowsAdvice extends Advice {
    
    }
    //所给对象必须实现一个或者多个针对特定类型的异常通知方法,格式如下
    afterThrowing([Method], [args], [target], subclassOfThrowable)
    //只有最后一个参数是必须的。因此异常通知方法对方法及参数的需求,方法的签名将从一到四个参数之间变化。

    最后还有一个是introduction advice,这个我想什么时候自己单独做个例子理解一下。

           做了个例子如下,想像一个用户登录场景:在登录之前,我们对其输入的用户名进行有效性检查;登录成功后,我们记上用户登录次数;如果登录失败,则进行异常处理。实现代码如下:

    package com.learn.spring.test.advisor;
    //登录的业务代码
    public interface LoginService {
        void login(String name, String password) throws UnauthorityException;
    }
    
    public class LoginServiceImpl implements LoginService {
    
        public void login(String name, String password) throws UnauthorityException {
                check(name, password);
                System.err.println(name + " is logining system...");
        }
        
        private void check(String name, String password) throws UnauthorityException {
                if("myyate".equals(name) && "pass".equals(password) ) {
                         System.err.println(name + " passed check....");
                } else {
                        throw new UnauthorityException("invalid password");
                }
        }
    }
    //用户名检查 拦截器
    public class LoginNameCheckInterceptor implements MethodBeforeAdvice {
    
        public void before(Method method, Object[] args, Object target) throws Throwable {
             System.err.println("check user's name is valid?");
             if(args[0] == null || "".equals(args[0].toString().trim())) {
                   throw new IllegalArgumentException();
             }
        }
    }
    //用户登录次数统计拦截器
    public class LoginCountInterceptor implements AfterReturningAdvice ...{
    
        public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable ...{
        System.err.println("Counting the login counts of " + args[0]);
        }
    }
    //异常处理拦截器
    public class ExceptionThrowInterceptor implements ThrowsAdvice {
        
        public void afterThrowing(Method m, Object[] args, Object target, IllegalArgumentException ex) throws Throwable {
        System.err.println("Login name is wrong, exception: " + ex);
        }
        
        public void afterThrowing(Method m, Object[] args, Object target, UnauthorityException ex) {
           System.err.println(target.getClass() + "." + m.getName() + 
               "() throw a exception: " + ex.getMessage());
        }
    }

    配置文件如下:

    <?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:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
               http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
               http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
    
        <bean id="loginServiceTarget"
            class="com.learn.spring.test.advisor.LoginServiceImpl"/>
            
        <bean id="loginNameCheckInterceptor"
            class="com.learn.spring.test.advisor.LoginNameCheckInterceptor"/>
            <!-- 
        <bean id="loginCheckInterceptor"
            class="com.learn.spring.test.advisor.LoginCheckInterceptor"/>
             -->
        <bean id="loginCountInterceptor"
            class="com.learn.spring.test.advisor.LoginCountInterceptor"/>
        <bean id="exceptionThrowInterceptor"
            class="com.learn.spring.test.advisor.ExceptionThrowInterceptor"/>
            
        <bean id="loginService" class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="target"><ref local="loginServiceTarget"/></property>
            <property name="proxyInterfaces">
                <list>
                    <value>com.learn.spring.test.advisor.LoginService</value>
                </list>
            </property>
            <property name="interceptorNames">
                <list>
                    <value>loginNameCheckInterceptor</value>
                    <value>loginCountInterceptor</value>
                    <value>exceptionThrowInterceptor</value>
                </list>
            </property>
        </bean>
    </beans>

    测试代码运行:

    public class Test {
    
        public static void main(String[] args) throws Exception {
            BeanFactory bf = 
                BeanFactoryFactory.getBeanFactory("beans.xml", Test.class);
            LoginService ls = (LoginService) bf.getBean("loginService");
            ls.login("myyate", "pass");
        }
    }

    输出结果:

    check user's name is valid?
    myyate passed check....
    myyate is logining system...
    Counting the login counts of myyate

    转载:https://blog.csdn.net/caolaosanahnu/article/details/7914595

  • 相关阅读:
    [问题2014S12] 复旦高等代数II(13级)每周一题(第十二教学周)
    [问题2014S09] 解答
    [问题2014S11] 复旦高等代数II(13级)每周一题(第十一教学周)
    [问题2014S08] 解答
    [问题2014S10] 复旦高等代数II(13级)每周一题(第十教学周)
    [问题2014S07] 解答
    [问题2014S09] 复旦高等代数II(13级)每周一题(第九教学周)
    [问题2014S08] 复旦高等代数II(13级)每周一题(第八教学周)
    怎么解决tomcat占用8080端口问题图文教程
    MySQL中删除重复数据只保留一条
  • 原文地址:https://www.cnblogs.com/cslgzl/p/10533335.html
Copyright © 2020-2023  润新知