Spring AOP中的introduction介绍

introduction和advice比较

  • introduction: 用于给目标引入新的接口,比如锁,状态功能时.生成一个mix-in的接口
  • advice: 只是在原有接口的基础上增加附加内容

introduction

通过IntroductionInterceptor接口实现

  • 实现一个introduction需要三个内容:
    • 将要添加的新接口的定义
    • 该新接口的实现,在实现的class中,必须实现Spring的IntroductionInterceptor接口
    • IntroductionAdvisor接口的实现
public interface IntroductionInterceptor extends MethodInterceptor {

	/*
  	 * 此方法用于判断该introduction实现是否实现了intf接口类
  	 * 所有对inf接口的调用方法都会转发给incoke方法,由invoke方法完成相应的任务
  	 *
	 * @param intf 接口类
	 * @return boolean 该introduction实现是否实现的接口类
  	 */
	boolean implementsInterface(Class intf);

	// invoke()方法来源于MethodInterceptor
	invoke(MethodInvocation invocation);
}
  • 示例: 添加一个aduitable功能

1.添加新的接口定义:

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

2.该新的接口的实现,必须实现Spring的IntroductionIntercepter:

/**
 * 2. auditable接口的实现,同时要实现IntroductionIntercepter接口
 */
public class AuditableMixin implements IntroductionInterceptor, Aduitable {

	/*
	 * 实现IntroductionInterceptor接口中的implementsInterface接口
	 */
	 public boolean implementsInterface(Class intf) {
	 	// AuditableMixin实现了Auditable类的功能
	 	return intf.isAssignableFrom(Auditable.class);
	 }

	public Object invoke(MethodInvocation m) throws Throwable {
		/*
		 * 对invoke中的参数m进行判断,当前的调用是否在implementsInterface范围内
		 * 即当前的调用是否是auditable接口中的方法
		 */
		if (implementsInterface(m.getMethod().getDeclaringClass())) {
			/*
			 * 调用引入的方法,来源于auditable接口,这样就可以给target添加新的auditable接口
			 * this就是对象本身
			 */ 
			 return m.getMethod().invoke(this, m.getArguments());
		} else {
			// 调用其余方法
			return m.proceed()
		}
	}
	// 实现auditable接口
	private Date lastModifiedDate;

	public Date getLastModifiedDate() {
		return lastModifiedDate;
	}
	public void setLastModifiedDate(Date lastModifiedDate) {
		this.latsModifiedDate = lastModifiedDate;
	}
}

通过DelegatingIntroductionInterceptor接口实现

  • introduction除了直接实现IntroductionInterceptor接口外,还可以通过继承DelegatingIntroductionInterceptor类实现
  • DelegatingIntroductionInterceptor默认实现了IntroductionInterceptor接口中的implementsInterfaceinvoke两个方法,仅仅需要自定义实现auditable接口
  • 示例: 通过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;
	}
}

Introduction总结

  • 上述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;
	}

	/**
	 * 修改invoke方法
	 */
	 public Object invoke(MethodInvocation m) throws Throwable {
	 	String name = mi.getMethod().getName();

	   /*
	  	* 如果已经是immutable,就不可以调用setXxx()方法
	    * 这样就改变了Target的行为,而不仅仅是添加行为
	    */
	  	if (immutable && name.indexOf("set") == 0) {
	  		throw new IllegalModificationException();
	  	}
	 	 return super.invoke(mi);
	 }
}

Spring中Introduction

  • Spring中的Introduction需要有Advisor: IntroductionAdvisor
  • Spring中使用Introduction的注意点:
    • Spring中使用的是动态AOP, 并没有像AspectJ使用静态的代码编译的方式生成AOP代码
    • 因此只有从SpringBeanFactory中得到的Introduction Bean才会被introduced
    • 直接在代码中new出来的target对象则不具有Introduction功能
    • 可以使用一个Factory来封装对Introduction的创建

猜你喜欢

转载自blog.csdn.net/JewaveOxford/article/details/107283525