Introdcution Advice

Spring AOP中的Introduction:

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

在Spring中,完成一个introduction需要三个内容:1、将要添加的新接口的定义,2、该新接口的实现,在实现的class中,必须实现Spring的IntroductionInterceptor接口(Spring in action原文有误),3、IntroductionAdvisor接口的实现。
public interface IntroductionInterceptor extends MethodInterceptor {
boolean implementsInterface(Class intf);
Object invoke(MethodInvocation invocation) //此方法来源于MethodInterceptor
}

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

public interface Auditable {//1、auditable接口的定义
void setLastModifiedDate(Date date);
Date getLastModifiedDate();
}

public class AuditableMixin
implements IntroductionInterceptor, Auditable {//2、auditable接口的实现,同时要实现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接口中的两个方法(implementsInterface,invoke)的默认实现,你仅需要实现auditable接口即可。

通过跟踪Spring源代码可以发现:DelegatingIntroductionInterceptor的implementsInterface (在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的创建。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值