您的位置:首页 > 运维架构

加快织入的自动化进程---DefaultAdvisorAutoProxyCreator

2014-11-14 17:59 369 查看
<span style="font-size:18px;">加快织入的自动化进程
在IoC容器中使用ProxyFactoryBean进行横切逻辑的织入固然不错,但是我们都是针对每个目标对象,然后给出它们各自所对应ProxyFactoryBean配置。
如果目标对象就那几个,那还应付的过来。但系统中那么多的业务对象可能都是目标对象,如果还用ProxyFactoryBean一个个的进行配置,估计会很累
所以得寻求更加快捷的方式.SpringAOP给出了自动代理(AutoProxy)机制,用以帮助我们解决ProxyFactoryBean的配置工作量较大的问题。
Spring AOP的自动代理的实现建立在IOC容器的BeanPostProcessor概念之上,通过BeanPostProcessor,可以在遍历容器中所有bean的基础上,对遍历到
的bean进行一些操作。根据这个BeanPostProcessor内部实现逻辑,即当对象实例化的时候不,为其生成代理对象并返回,从而达到代理对象自动生成目的。

可用的AutoProxyCreator
Spring AOP 在org.springframework.aop.framework.autoproxy包中提供了两个常用的AutoProxyCreator,即BeanNameAutoProxyCreator 和  DefaultAdvisorAutoProxyCreator

这里主要来介绍下DefaultAdvisorAutoProxyCreator。
DefaultAdvisorAutoProxy可以算是全自动的,我们只需要在ApplicationContext的配置文件中注册一个DefaultAdvisorAutoProxy的bean定义就可以了,剩下的事情由
DefaultAdvisorAutoProxy全部搞定。下面来展示一个具体的实现例子

ICounter接口定义及相关具体实现类
public interface ICounter {

void resetCounter();
int getCounter();
}

ICounter有两个实现类ICounterImpl1和ICounterImpl2

public class CounterImpl implements ICounter {
private int counter;
@Override
public void resetCounter() {
// TODO Auto-generated method stub
counter = 0;
}
@Override
public int getCounter() {
// TODO Auto-generated method stub
counter++;
return counter;
}
}

public class CounterImpl2 implements ICounter{
private int counter;
@Override
public void resetCounter() {
// TODO Auto-generated method stub
counter=10;
}
@Override
public int getCounter() {
// TODO Auto-generated method stub
counter--;
return counter;
}
}

ITask接口定义及相关实现类
public interface ITask {
void execute();
}

ITask也有两个实现类 MockTask 和 FakeTask

public class MockTask implements ITask{
@Override
public void execute() {
// TODO Auto-generated method stub
System.out.println("taskmock executed");
}
}

public class FakeTask implements ITask{
@Override
public void execute() {
// TODO Auto-generated method stub
System.out.println(" facktask executed");
}
}

我还自定义了一个简单的拦截类PerformanceMethodInterceptor,可以应用到具体的类或其方法中

public class PerformanceMethodInterceptor implements MethodInterceptor{
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("start.....");//相当于beforeAvice
Object returnVal=invocation.proceed();
System.out.println("stop....");//相当于AfterAdvice
return returnVal;
}
}

DefaultAdvisorAutoProxyCreator的使用配置示例
<?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
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
<bean id="counterImpl1" class="aop.spring.deleIntroduction.CounterImpl1"></bean>
<bean id="counterImpl2" class="aop.spring.deleIntroduction.CounterImpl2"></bean>

<bean id="mockTask" class="aop.spring.deleIntroduction.MockTask"></bean>
<bean id="fakeTask" class="aop.spring.deleIntroduction.FakeTask"></bean>

<bean name="pointcut"
class="org.springframework.aop.support.NameMatchMethodPointcut">
<property name="mappedName" value="execute"></property>
</bean>
<!-- 有多个方法时 -->
<bean name="pointcut2" class="org.springframework.aop.support.NameMatchMethodPointcut">
<property name="mappedNames">
<list>
<value>resetCounter</value>
<value>getCounter</value>
</list>
</property>
</bean>

<bean id="logAdvisor1" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="pointcut" ref="pointcut"></property>
<property name="advice">
<bean id="performaceInterceptor1"
class="aop.spring.deleIntroduction.PerformanceMethodInterceptor">
</bean>
</property>
</bean>

<bean id="logAdvisor2" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="pointcut" ref="pointcut2"></property>
<property name="advice">
<bean id="performaceInterceptor2" class="aop.spring.deleIntroduction.PerformanceMethodInterceptor"></bean>
</property>
</bean>
</beans>

将DefaultAdvisorAutoProxyCreator注册到容器后,它就会自动搜寻容器类所有Advisor,然后根据各个Advisor所提供的拦截信息,
为符合条件的容器中的目标对象生成相应的代理对象。注意DefaultAdvisorAutoProxyCreator只对Advisor有效,因为只有Advisor
才既有Pointcut信息以捕捉符合条件的目标对象,又有相应的Advice。
使用DefaultAdvisorAutoProxyCreator对容器内所有bean定义对应的对象进行自动代理之后,我们从容器中取得对象实例,就都是代理
后已经包含了织入的横切逻辑的代理对象了,除非该对象不符合Pointcut规定的拦截条件。

建立一个测试类如下

public class AutoProxyCreaterTest {
@Test
public void test() {
ApplicationContext ctx=new ClassPathXmlApplicationContext("/beans1.xml");
ITask task1=(ITask) ctx.getBean("mockTask");
task1.execute();
ITask task2=(ITask) ctx.getBean("fakeTask");
task2.execute();
ICounter counter1=(ICounter) ctx.getBean("counterImpl1");
System.out.println(counter1.getCounter());
ICounter counter2=(ICounter)ctx.getBean("counterImpl1");
System.out.println(counter2.getCounter());
ICounter counter3=(ICounter)ctx.getBean("counterImpl2");
System.out.println(counter3.getCounter());
}
}

输出的结果如下:
start.....
task executed
stop....

start.....
facktask executed
stop....

start.....
stop....
1

start.....
stop....
2

start.....
stop....
-1

从结果可以看出每个对象都被加上了横切逻辑
所以这里  ITask task1=(ITask) ctx.getBean("mockTask");这些返回的都不是目标对象本身而是被织入了横切逻辑的对象。
通过自己动手实践,我基本上就了解了DefaultAdvisorAutoProxy的用法了。
真的是动手实践很重要很重要.

</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: