jinfeng_wang

G-G-S,D-D-U!

BlogJava 首页 新随笔 联系 聚合 管理
  400 Posts :: 0 Stories :: 296 Comments :: 0 Trackbacks

Spring AOP中的Introduction

正如前面已经提到的,Introduction和前面的四个advice是有很大的区别的,introduction用于给target引入新的接口(例如锁,状态等功能),生成一个mix-in的接口。而普通的advice只是在原有接口基础上增加附加内容。

Spring中,完成一个introduction需要三个内容:1、将要添加的新接口的定义,2、该新接口的实现,在实现的class中,必须实现SpringIntroductionInterceptor接口(Spring in action原文有误),3IntroductionAdvisor接口的实现

public interface IntroductionInterceptor extends MethodInterceptor {

  boolean implementsInterface(Class intf);

java.lang.Object invoke(MethodInvocation invocation) //此方法来源于MethodInterceptor

}

其中implementsInterface方法返回一个boolean值,此方法用于判断该introduction实现是否实现了某个接口――intf参数。所有对intf接口的调用都会转发给invoke方法,由invoke方法完成相应的任务。下面给出例子(给某个类添加是否auditable功能):

            public interface Auditable {//1auditable接口的定义

void setLastModifiedDate(Date date);

Date getLastModifiedDate();

}

public class AuditableMixin

implements IntroductionInterceptor, Auditable {//2auditable接口的实现,同时要实现IntroductionInterceptor接口

public boolean implementsInterface(Class intf) {

return intf.isAssignableFrom(Auditable.class);  // AuditableMixin实现了Auditable类的功能

}

public Object invoke(MethodInvocation m) throws Throwable {

if (implementsInterface(m.getMethod().getDeclaringClass())) {

//invoke的参数m进行判断,当前的调用是否在implementsInterface范围内,即,当前的调用是否是auditable接口中的方法?

return m.getMethod().invoke(this, m.getArguments());

//这里的this就是自己,调用引入的方法(属于auditable接口的方法),这样也就给target添加了新的auditable接口。

} else {

return m.proceed();//其他方法的调用。

}

}

private Date lastModifiedDate; //实现auditable接口。

public Date getLastModifiedDate() {

return lastModifiedDate;

}

public void setLastModifiedDate(Date lastModifiedDate) {

this.lastModifiedDate = lastModifiedDate;

}

}

Spring中,除了上面直接实现IntroductionInterceptor接口之外,还可以通过继承DelegatingIntroductionInterceptor类实现。其中DelegatingIntroductionInterceptor给出了IntroductionInterceptor接口中的两个方法(implementsInterfaceinvoke)的默认实现,你仅需要实现auditable接口即可。

通过跟踪Spring源代码可以发现:DelegatingIntroductionInterceptorimplementsInterface (在IntroductionInfoSupport类中)和invoke方法与上面的代码的形式基本一致。下面是利用DelegatingIntroductionInterceptor写出的AuditableMixin

public class AuditableMixin

extends DelegatingIntroductionInterceptor implements Auditable {

private Date lastModifiedDate;

public Date getLastModifiedDate() {

return lastModifiedDate;

}

public void setLastModifiedDate(Date lastModifiedDate) {

this.lastModifiedDate = lastModifiedDate;

}      

}

    注意到一点:上面的两个AuditableMixin的实现都仅仅是给Target添加行为,但是未曾改变Target的原有行为(因为在invoke方法的实现中,还是会转发给Target)。如果需要改变Target的行为(例如给Target增加lock接口,一旦处于locked状态,那么再调用Target的方法就会出现异常),这就需要自己写代码修改invoke方法。

public class ImmutableMixin

extends DelegatingIntroductionInterceptor implements Immutable {

private boolean immutable;

public void setImmutable(boolean immutable) {

this.immutable = immutable;

}

public Object invoke(MethodInvocation mi) throws Throwable {

String name = mi.getMethod().getName();

if (immutable && name.indexOf("set") == 0) { //这里一旦已经是immutable了,那么就不可以调用setXXX方法了,这也就改变了Target的行为,而不是前面的仅增加接口。

throw new IllegalModificationException();

}

return super.invoke(mi);

}

}

 

Spring中的Introduction需要有自己的advisor: IntroductionAdvisor

剩下的也就是和前面一样的xml文件的编写了。


Spring中使用Introduction需要注意的问题:
    由于Spring使用的是动态AOP,并没有象AspectJ使用静态的代码预编译的方式生成AOP代码,因此只有你从Spring的BeanFactory中得到的Introduction Bean才会已经被introducted,而直接在代码中new出来的target对象则不具有Intorduction功能。 你可以使用一个Factory,封装对Introduction的创建。
posted on 2005-03-03 10:49 jinfeng_wang 阅读(2829) 评论(0)  编辑  收藏 所属分类: spring

只有注册用户登录后才能发表评论。


网站导航: