Spring从菜鸟到高手(二)AOP的真正实现

 

经过了前面一章的学习大家基本理解了SpringAOP的简单工作原理,但是那只是最基本的一些操作,Spring的设计师们知道我们不想在诸如得到一个代理类、需要实现哪些接口 这些琐碎的事情上牵扯过多的经历,毕竟我们是中国软件产业的栋梁我们还要做更重要的事情。^_^  所以他们给我们准备了好多好东西,下面我就来介绍一下

拦截器接口MethodBeforeAdvice 所在包org.springframework.aop.MethodBeforeAdvice

功能:可以在调用的目标方法之前加入功能。方法:

voidbefore(Method method, Object[] args, Object target)

拦截器接口AfterReturningAdvice  所在包org.springframework.aop.AfterReturningAdvice

功能:可以在调用的目标方法之后加入功能。方法:

voidafterReturning(Object returnValue, Method method, Object[] args, Object target)

拦截器接口MethodInterceptor 所在包 org.aopalliance.intercept.MethodInterceptor

功能:可以在调用的目标方法前后(也可以叫周围)加入功能。方法:

 java.lang.Objectinvoke(MethodInvocation invocation)

接口MethodInvocation 所在包 org.aopalliance.intercept.MethodInvocation

MethodInvocation 接口从父接口Joinpoint处继承到一个方法

java.lang.Objectproceed()

调用proceed方法方法用于执行目标类的目标方法。

下面我通过现实的代码来讲解Spring中AOP的使用方法,我还使用我以前例子中的接口Foo和实现此接口的类FooClass【开发环境为Eclipse】

便于大家阅读我将全部代码贴上来,首先是接口Foo,我在这个接口中增加了一个打印整数的方法

public interface Foo {
 public void printMessage(String message);
 public void printInteger(int num);
}

实现Foo接口的类FooClass

public class FooClass implements Foo {

 public void printMessage(String message) {
  
  System.out.println(this.getClass().getName()+" "+message);
 }
 public void printInteger(int num)
 {
  System.out.println(this.getClass().getName()+" "+num);
 }
}

 实现上面三个拦截器接口【AfterReturningAdvice,MethodBeforeAdvice,MethodInterceptor 】的类MyAdvice

import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;

public class MyAdvice implements AfterReturningAdvice,MethodBeforeAdvice,MethodInterceptor
{

 public void afterReturning(Object arg0, Method arg1, Object[] arg2,
   Object arg3) throws Throwable {
  Log log = LogFactory.getLog(MyAfterReturningAdvice.class);
  log.info("我在程序运行之后出现");
  
 }

 public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
  Log log = LogFactory.getLog(MyAfterReturningAdvice.class);
  log.info("我在程序运行之前出现");
  
 }

 public Object invoke(MethodInvocation arg0) throws Throwable {

  Log log = LogFactory.getLog(MyAfterReturningAdvice.class);
  log.info("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
  Object obj = arg0.proceed();
  log.info("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
  return obj;
 }

}

由于我使用的Junit测试,所以有一个Junit测试类AOPJunitTest

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import junit.framework.TestCase;

public class AOPJunitTest extends TestCase {
 ApplicationContext act = null; //使用的应用上下文类
 protected void setUp() throws Exception {
  super.setUp();
  this.act = new ClassPathXmlApplicationContext("/applicationContext.xml");//读取XML配置文件
  
 }
 public void testprintMessage()
 { 
   Foo foo = (Foo)act.getBean("proxy");//通过依赖注入得到FooClass对象的实例这个对象是Spring的一个类                                                                 org.springframework.aop.framework.ProxyFactoryBean这个类需要三个注入分别是

 voidsetTarget(Object target) 得到注入一个目标对象(真正要干活的类)

voidsetProxyInterfaces(String[] interfaceNames) 目标对象所实现的接口数组
voidsetInterceptorNames(String[] interceptorNames) 拦截器数组(因为我们有多种拦截器)

   foo.printMessage("Hello!");
   foo.printInteger(20);
 }
}

下面是我们的XML配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
 <bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
  <property name="target">
   <ref bean="fooClass"/>
  </property>
  
  <property name="proxyInterfaces">
   <value>Foo</value>
  </property>
  
  <property name="interceptorNames">
   <list>
    <value>interceptorReturning</value>
   </list>
  </property>
 </bean>
 
 
 <bean id="fooClass" class="FooClass"></bean>
 <bean id="interceptorReturning" class="MyAdvice"></bean>
  
 </beans>

程序运行结果

INFO - $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
INFO - 我在程序运行之前出现
FooClass Hello!
INFO - 我在程序运行之后出现
INFO - $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
INFO - $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
INFO - 我在程序运行之前出现
FooClass 20
INFO - 我在程序运行之后出现
INFO - $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值