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


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


<bean id="componentadvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
        
        <property name="mappedName" value="*business1"/>
        
        <property name="advice" ref="validatebeforeadvice"/>
    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>componentadvisorvalue>
            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”属性值。


    <bean id="componentadvice" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        
        <property name="pattern" value=".*business(1|2)"/>
        
        <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文件


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


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



<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>validateAdvisorvalue>
            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完成自动代理。


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


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



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


    <bean id="introductionproxycreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
    
        <property name="beanNames">
            <list>
                <value>componentvalue>
            list>
        property>
        
        <property name="interceptorNames" value="validateAdvisor"/>
    bean>

测试类如上。

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

你可能感兴趣的:(Spring)