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
如果分开的该怎么实现呢?
Introduction的Advice的实现
最新推荐文章于 2023-10-13 21:54:37 发布