Spring中的Advice类型及其应用
2012-08-28 09:21
274 查看
/article/9196591.html
在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 通知。它不需要
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
在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
相关文章推荐
- Spring中的Advice类型及其应用
- Spring中的Advice类型及其应用
- Spring---AOP基本概念以及Advice5种类型的通知注解应用实例
- Web服务及其应用类型
- 第43讲:Scala中类型变量Bounds代码实战及其在Spark中的应用源码解析
- 我的php学习笔记(二)php基本数据类型、基本语法和基本运算类型及其应用
- 数据类型及其应用
- Spring之Advice应用(上)
- 第43讲:Scala中类型变量Bounds代码实战及其在Spark中的应用源码解析学习笔记
- 详解spring-boot集成elasticsearch及其简单应用
- 由JDBC浅谈JNDI及其在WebSphere中的配置和企业级应用中DB Session在Spring下的管理
- js数据转换boolean类型和短路逻辑-及其应用;
- 类型名字的获取及其应用(g++ only)
- Scala深入浅出进阶经典 第48讲:Scala类型约束代码实战及其在Spark中的应用源码解析
- 第43讲:Scala中类型变量Bounds代码实战及其在Spark中的应用源码解析
- Redis的hash数据类型及其应用场景解析---购物车
- Spring学习笔记——Spring如何装配各种类型的属性以及实际应用
- AOP及其在Spring中的应用(一)
- 传智播客-ejb3(2)-bean类型、jboss基本应用、本地组件和远程组件及其底层实现原理简介
- j2ee的spring应用中注入boolean类型的数据会报异常