Introduction的Advice的实现

Introduction的Advice的实现
 Introduction可以在不改动目标类定义的情况下,为目标类增加新的属性和行为。
 在Spring中,为目标对象添加新的属性和行为必须声明相应的接口以及相应的实现。这样,再通过特定的拦截器将新的接口定义以及实现类中
 的逻辑附加到目标对象上。之后,目标对象(确切的说,是目标对象的代理对象)就拥有了新的状态和行为。这个特定的拦截器就是
 org.springframework.aop.IntroductionInterceptor,其定义如下
 public interface IntroductionInterception extends MethodInterceptor,DynamicIntroductionAdvice{}
 public interface DynamicIntroductionAdvice extends Advice
 {
    boolean implementsInterface(Class intf)
	 
 }
 
 IntroductionInterceptor继承了MethodInterceptor以及DynamicIntroductionAdvice。通过DynamicIntroductionAdvice,可以界定当前的
 IntroductionInterceptor为哪些接口提供相应的拦截功能。通过MethodInterceptor,IntroductionInterceptor 就可以处理新添加的接口上
 的方法调用了
    如果把每个目标对象实例看作盒装牛奶生产线上的那一盒盒牛奶的话,那么生产合格证就是新的Introduction逻辑,而introductionInterceptor
就是把这些生产合格证贴到一盒盒牛奶上的那个人。
   要对目标对象进行拦截并添加Introduction的逻辑,我们可以直接扩展IntroductionInterceptor,然后在子类的invoke方法中实现所有的拦截逻辑
除非特殊情况下需要直接扩展IntroductionInterceptor,大多数时候,直接使用Spring提供的两个现成的实现类就可以了.

 DelegatingIntroductionInterceptor 和 DelegatePerTargetObjectIntroductionInterceptor  
 
 下面是我实现Introduciton的具体例子
 
 首先给出ISomeBean接口及其实现类
 public interface ISomeBean {
	public void doSth();
}

public class ISomeBeanImpl implements ISomeBean{
	@Override
	public void doSth() {
		// TODO Auto-generated method stub
		System.out.println("do something");
	}
}


使用IntroductionInterceptor为ISomeBean添加新的状态或者行为,我们可以按照如下的步骤进行
(1)为新的状态和行为定义接口
    public interface IOtherBean {
	public void doOther();
}

下面同时实现了IntroductionInterceptor,其实我还不是很明白为什么写成这样
public class SomeBeanIntroductionInterceptor implements IOtherBean,IntroductionInterceptor{
	/**
	 * 判断调用的方法是否为指定类中的方法
	 * 如果Method代表了一个方法 那么调用它的invoke就相当于执行了它代表的这个方法
	 */
	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		if(implementsInterface(invocation.getMethod().getDeclaringClass())){
			System.out.println("zhangsi");
			return invocation.getMethod().invoke(this, invocation.getArguments());
		}
		return invocation.proceed();
	}
	/**
	 * 判断clazz是否为给定接口IOtherBean的实现
	 */
	@Override
	public boolean implementsInterface(Class clazz) {
		return clazz.isAssignableFrom(IOtherBean.class);
	}
	@Override
	public void doOther() {
		System.out.println("do other thing");
	}
}

配置文件定义如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

	xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-2.5.xsd
        http://www.springframework.org/schema/tx
         http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
	<!-- 目标对象 -->
	<bean id="someBeanTarget" class="com.spring.targetImpl.ISomeBeanImpl" />

	<!-- 通知 -->
	<bean id="someBeanAdvice" class="aop.spring.advice.SomeBeanIntroductionInterceptor"></bean>

	<!-- 通知者,只能以构造器方法注入 -->
	<!-- DefaultIntroductionAdvisor(Advice advice, IntroductionInfo introductionInfo) -->
	<!-- introductionInfo - the IntroductionInfo that describes the interface 
		to introduce (may be null) -->
	<bean id="introductionAdvisor"
		class="org.springframework.aop.support.DefaultIntroductionAdvisor">
		<constructor-arg ref="someBeanAdvice" />
		<constructor-arg value="aop.spring.target.IOtherBean" />
	</bean>

	<!-- 代理,将我们的切面织入到目标对象 -->
	<bean id="someBeanProxy" class="org.springframework.aop.framework.ProxyFactoryBean">

		<!-- 若目标对象实现了代理接口,则可以提供代理接口的配置 -->
		<property name="proxyInterfaces" value="aop.spring.target.ISomeBean" />

		<!-- 配置目标对象 -->
		<property name="target" ref="someBeanTarget" />

		<!-- 配置切面 -->
		<property name="interceptorNames">
			<list>
				<value>introductionAdvisor</value>
			</list>
		</property>
	</bean>
</beans>


测试类如下:
public class AdviceTest {

	@Test
	public void test() {
	AbstractApplicationContext ctx=new ClassPathXmlApplicationContext("/beans.xml");
	/**
	 * 将代理对象强制转换为目标对象的具体类型
	 */
	ISomeBean weaver=(ISomeBean) ctx.getBean("someBeanProxy");
	weaver.doSth();
	System.out.println("=====");
	((IOtherBean)weaver).doOther();
	}
}
我理解的是获得weaver对象同时具备了ISomeBean和IOtherBean的属性,所以可以被当做这两个对象来使用。
这就是Introduction的典型应用。就是有一点不明白的是为什么IOtherBean的实现类要同时实现IntroductionInterceptor
如果分开的该怎么实现呢?
















	

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值