Spring-AOP更加细化的织入时机

在上文 Spring学习:AOP思想中已经介绍了,AOP思想,以及springAOP的初步使用方法。在上文中,所介绍到的MethodBeforeAdvice是为代理对象的每个方法执行前执行用户验证。那么现在就有一个问题,如果只是business1()和business2()执行前需要用户验证,我们应该怎么做?下面来介绍。

细化的SpringAOP织如时机

回顾一下上次的内容,有一个component类继承了Icomponent接口,并实现了接口的三个业务逻辑business1(),business2(),business3()我们希望在每个方法执行前调用用户验证。

//Icomponent接口
package com.cst.spring.lab3;

public interface Icomponent {

    public void business1();
    public void business2();
    public void business3();
}

//component类
package com.cst.spring.lab3;

/**
 * @author Cst
 *
 */
public class Component implements Icomponent{

    public void business1()
    {
        System.out.println("业务1");
    }

    public void business2()
    {
        System.out.println("业务2");
    }
    public void business3()
    {
        System.out.println("业务3");
    }

}

我们可以通过实现MethodBeforeAdvice接口来实现所需要的要求,详看上文。
那么现在我们只需要为business1()执行前执行用户验证,怎么做?

Spring内建的Pointcut都有对应的PointcutAdvisor,
使用org.springframework.aop.support.NameMatchMethodPointcutAdvisor提供静态的Pointcut实例,使用表达式指定Advice应用目标上的方法名称,或者用*来指定。

1.实现MethodBeforeAdvice接口实现ValidateBeforeMethod类

public class ValidateBeforeMethod implements MethodBeforeAdvice{

    public void before(Method arg0, Object[] arg1, Object arg2)
            throws Throwable {
        // TODO Auto-generated method stub
        this.validate();
        System.out.println(arg0);

    }

    public void validate()
    {
        System.out.println("验证用户");
    }
}

2.配置xml

<!-- 定义component-->
<bean id="component" class="com.cst.spring.lab3.Component"/>

<!--为busines1,2添加MethodBeforeAdvice-->
<bean id="componentadvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
        <!-- 为希望的方法添加advice -->
        <property name="mappedName" value="*business1"/>
        <!-- 添加的advice -->
        <property name="advice" ref="validatebeforeadvice"/>
    </bean>

<!--为component绑定Advisor-->
<bean id="componentproxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="proxyInterfaces" value="com.cst.spring.lab3.Icomponent"/>
        <property name="target" ref="component"/>
        <property name="interceptorNames">
            <list>
                <value>componentadvisor</value>
            </list>
        </property>
    </bean>

3.测试类

public class AopExample {

    public static void main(String[] args) {

        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
        Icomponent icom=(Icomponent)context.getBean("componentproxy");
        icom.business1();
    }

}

如果需要为busines1()和business2()又如何做?

Spring 提供org.springframework.aop.support.RegexpMethodPointcutAdvisor
使用正则表达式来编写Pointcut表达式,其值为“pattern”属性值。

<!--为busines1,2添加MethodBeforeAdvice-->
    <bean id="componentadvice" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <!-- 使用正则表达式为希望的方法添加advice -->
        <property name="pattern" value=".*business(1|2)"/>
        <!-- 添加的advice -->
        <property name="advice" ref="validatebeforeadvice"/>
    </bean>

Introduction

在Spring中,Introduction是一种特殊的Advice,直接介入整个对象的行为,好像对象凭空多了可操作的行为,为对象动态加入原先所没有的职责。

可以通过实现org.springframework.aop.IntroductionInterceptor来实现Introduction

在不修改原始文件的情况下,
将增加的可操作方法放在另一接口中将Introduction织入到目标对象上,使用org.springframework.aop.support.DefaultIntroductionAdvisor

也就是说我们可以将用户验证方法使用Introduction织入到目标对象中。实现如下

1.定义用户验证接口类


public interface IValidate {

    public void Validate();
}

2.实现Introduction


//实现了接口Ivalidate与IntroductionInterceptor
public class ValidateIntroduction implements IValidate, IntroductionInterceptor {

    public Object invoke(MethodInvocation arg0) throws Throwable {
        if(implementsInterface(arg0.getMethod().getDeclaringClass()))
        {
            return arg0.getMethod().invoke(this, arg0.getArguments());
        }
        else
        {
            return arg0.proceed();
        }
    }

    //判断是否继承验证接口
    public boolean implementsInterface(Class arg0) {

        return arg0.isAssignableFrom(IValidate.class);
    }

    public void Validate() {
        System.out.println("用户验证");
    }

}

3.配置xml文件

<!-- componentbean -->
<bean id="component" class="com.cst.spring.lab3.Component"/>

<!-- introduction -->
    <bean id="validateintroduction" class="com.cst.spring.lab3.ValidateIntroduction"/>


<!-- Advisor -->
<bean id="validateAdvisor" class="org.springframework.aop.support.DefaultIntroductionAdvisor">
        <constructor-arg ref="validateintroduction"/>
        <constructor-arg value="com.cst.spring.lab3.IValidate"/>
    </bean>

<!-- 绑定到目标对象 -->
<bean id="componentproxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="proxyInterfaces" value="com.cst.spring.lab3.Icomponent"/>
        <property name="target" ref="component"/>
        <property name="interceptorNames">
            <list>
                <value>validateAdvisor</value>
            </list>
        </property>
    </bean>

4.测试类

public class AopExample {

    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
        Icomponent icom=(Icomponent)context.getBean("component");


        ((IValidate)icom).Validate();
        icom.business1();
        ((IValidate)icom).Validate();
        icom.business2();

    }

}

以上便实现了使用Introduction在business1(),business2()前进行用户验证。

自动代理Autoproxing

利用BeanNameAutoProxyCreator完成自动代理。

<!-- componentbean -->
<bean id="component" class="com.cst.spring.lab3.Component"/>

<!-- introduction -->
    <bean id="validateintroduction" class="com.cst.spring.lab3.ValidateIntroduction"/>

<!-- Advisor -->

    <bean id="validateAdvisor" class="org.springframework.aop.support.DefaultIntroductionAdvisor">
        <constructor-arg ref="validateintroduction"/>
        <constructor-arg value="com.cst.spring.lab3.IValidate"/>
    </bean>

<!-- 利用BeanNameAutoProxyCreator完成自动代理 -->
    <bean id="introductionproxycreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
    <!-- 代理目标 -->
        <property name="beanNames">
            <list>
                <value>component</value>
            </list>
        </property>
        <!-- Advisor -->
        <property name="interceptorNames" value="validateAdvisor"/>
    </bean>

测试类如上。

以上便是本文的全部内容。有错误请指出,谢谢

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值