Spring AOP Advices

Advices实现了Aspect的真正逻辑,具体来说在java中就是一个类或更细粒度的设计成一个方法(由一个类集中管理多个Advices)。按织入Targets的时机不同,spring提供了几种不同的Advices,如:Before AdvicesAfter AdvicesAround AdvicesThrow Advice

一、Before Advices

Before Advices会在目标对象的方法执行之前被调用,可以调用org.springframework.aop.MethodBeforeAdvice接口来实现Before Advice的逻辑,该接口的定义如下:

public interface MethodBefore extends BeforeAdvice{

void before(Method method,Object[] args,Object target) throws Throwable;

}

BeforeAdvice继承自Advice接口,而这两个都是标签接口。没有任何方法。

before()方法会在目标对象(Target)所指定的方法执行之前被执行,可以取得被执行的Method实例、参数对象数组以及目标对象。

例子:

public interface IHello{

public void hello(String name);

}

HelloSpeaker类:

public class HelloSpeaker implements IHello{

public void hello(String name){

System.out.println("Hello" + name);

}

}

HelloSpeaker相当于一个组件,如果没有源代码,对它的方法前加一些日志功能,可以实现MethodBeforeAdvice接口,例如:

.....

public class LogBeforeAdvice implements MethodBeforeAdvice{

private Logger logger = Logger.getLogger(this.getClass().getName());

public void before(Method method,Object[] args,Object target)) throws  Throwable{

logger.log("method starts" + method);

}

}

二、After Advices

After Advices会在目标方法执行之后被调用,可以实现org.springframework.aop.AfterReturningAdvice接口来实现After Advice的逻辑,AfterReturningAdvice接口的定义如下:

public interface AfterReturningAdvice extends Advice{

void afterReturning(Object returnValue,Method m,Object[] args,Object target)

throws Throwable;

}

实现类:

public class LogAfterAdvice implements AfterReturningAdvice{

private Logger logger = Logger.getLogger(this.getClass().getName());

public void afterReturning(............){

logger.log("method ends" + method);

}

}

配置文件中加入After Advice的实例,在ProxyFactoryBeaninterceptorNames中增加LogAfterAdvice的引用:

<bean  />

<bean id = "logAfterAdvice" class="..." />

<bean id = "helloSpeaker" class="..." />

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

<property name = "proxyInterfaces" value="...IHello" />

<property name = "target" value = "....HelloSpeaker" /.

<property name = "interceptorNames" >

<list>

<value>logBeforeAdvice</value>

<value>logAfterAdvice</value>

</list>

</bean>

其实可以设计一个类同时实现这两个接口,这里只是演示才将Advice分开。

三、Around Advices

如果在方法执行前后加入Advices的服务,可以直接通过实现org.aopalliance.intercept.MethodInterceptor接口。定义如下:

public interface MethodInterceptor{

public Object invoke(MethodInvocation methodInvocation) throws Throwable;

}

这接口是由AOP Alliance所指定,可以相容于遵守AOP Alliance规范的AOP框架。

与之前不同的是,MethodInterceptorinvoke()方法中,要自行决定是否要执行methodInvocationproceed()方法来执行目标对象。proceed()返回执行结果,所以可以在invoke()结束之前,有机会修改这个对象并返回其他值。例如:

public class LogInterceptor implements MethodInterceptor{

private Logger logger = Logger.getLogger(this.getClass().getName());

public Object invoke(MethodInvocation methodInvocation) thorws Throwable{

logger.log("method start" + methodInvocation.getMethod());

Object result = null;

try{

result = methodInvocation.proceed();

}

finally{

logger.log("method ends" + methodInvoacation.getMehod());

}

return result;

}

}

配置文件定义与之前相同。只是改名字罢了。

四、Throw Advices

若想在异常发生时通知某些服务对象某些事,可以使用Throws Advice,必须实现org.springframework.aop.ThrowsAdvice接口,然而这个接口并没有定义任何方法,可以自己定义afterThrowing方法,符合一下形式:

afterThrowing([Method],[args],[target],subclassOfThrowable);

异常发生时,Throw Advice只是执行对应的方法,并不能在Throws Advice中将异常处理掉,在Throw Advice执行完毕后,原先的异常仍被传播至应用程序之中,异常处理仍是应用程序本身所要负责的,如果要在Throw Advice处理时中止应用程序的处理流程,做法是丢出其他异常。例如:

public interface IHello{

public void hello(String name) throws Throwable;

}

接着定义类,在hello()方法中模拟异常发生:

public class HelloSpeaker implements IHello{

public void hello(String name) throws Throwable{

System.out.println("Hello" + name);

throw new Exception("发生异常...");

}

}

如果想在应用程序丢出异常时,介入Throw Advice提供一些服务,例如记录一些异常信息,则可以实现ThrowAdvice接口。

public class SomeThrowAdvice implements ThrowsAdvice{

private Logger logger = Logger.getLogger(this.getClass().getName());

public void afterThrowing(Method method,Object[] args,Object target,Throwable subclass){

logger.log(subclass + "Exception wa thrown in" + method);

}

}

客户程序:

.......

ApplicationContext ac = new ClassPathXmlApplicationContext("conf.xml");

IHello helloProxy = ac.getBean("helloProxy");

try{

helloProxy.hello("Justin");

}

catch(Throwable throwable){

System.err.println(throwable);

}

上面可以看出Throw 并不介入异常的处理,而是增加了日志记录功能,异常处理在应用程序本身中处理。

 

相关文章:

  • 2021-08-04
  • 2021-12-04
  • 2021-08-03
  • 2021-12-19
  • 2021-10-17
猜你喜欢
  • 2021-12-26
  • 2021-04-30
  • 2021-08-14
  • 2022-01-26
  • 2021-06-11
  • 2021-06-30
  • 2021-09-16
相关资源
相似解决方案