Spring中AOP,一个query与check的…

  接着前一章,我们根据query与check的横切图来真真正正用Java实现一遍,更有助于理解这整个AOP过程。AOP的实现应该是运用了反射机制(Java Reflection)[1],通过反射,在运行中读取编译好的类,从而获取类名、方法名,并进行一系列操作(有点类似破解的味道)
  所以,AOP是不安全的!(大误)……其实类似Spring这样,把类的创建权交给别人本身,就是不太安全的。除非你真的非常信赖Spring……当然,这也是Spring和AOP为什么开源、流行的原因,大家都必须可以检查是否留有后门。这里我们假设AOP没有后门,不会给我们的query加上除了我们相加的check之外的任何函数。
  在第一章我们看到的图:
Spring中AOP,一个query与check的实现(二)——详细完整Java代码实现
根据这个图来写个AOP,以下是我们的工作目录:所有文件均在源包那儿,测试包内没有文件 (我们使用最纯粹的MainClass函数来运行我们的代码)
Spring中AOP,一个query与check的实现(二)——详细完整Java代码实现
还记得之前说过,Spring就是一个类工厂,按照订单需求生成Object。但是我一个手机工厂,总不能给你一台不能上网的电脑吧?所以其实这个需求也是有限定的,这个限定就是一个interface。我们虽然希望所有的query()方法都需要检查,但是还是得限定在一个Class里面 (若是AOP有更强大的功能,我们再探索,目前教程先举这个限定死的简单的例子)

文件QueryInterface.java
package aop;
public interface QueryInterface {
    void query1();
    void query2();
    void query3();
    void query4();
    void queryN();
}

然后我们实现这个接口:
文件QueryClass.java
package aop;
public class QueryClass implements QueryInterface{
    @Override  public void query1() {
        System.out.println("Get Data From Database.从数据库取数据");
    }
    @Override  public void query2() {
        System.out.println("[方法二]Get Data From Database.从数据库取数据");
    }
    @Override  public void query3() {
        System.out.println("[方法三]Get Data From Database.从数据库取数据");
    }
    @Override public void query4() {
        System.out.println("[方法四]Get Data From Database.从数据库取数据");
    }
    @Override  public void queryN() {
        System.out.println("[方法九九九]Get Data From Database.从数据库取数据");
    }
}

  可以看到我们有不同的query方法。接下来是重点,我们如何AOP呢?我们使用Spring的AOP,需要引入一个额外的包,叫aopalliance.jar( 可以百度搜一下,不过别用那个aopalliance-alpha1.jar,它还不支持Spring4)。这个包提供了一系列AOP方法。加载完包之后,我们新建一个CheckClass类:
文件CheckClass.java
package aop;

import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;

public class CheckClass implements MethodBeforeAdvice,AfterReturningAdvice{
    @Override
    public void before(Method mtd, Object[] arg1, Object arg2)throws Throwable {
        check();
    }

    @Override
    public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
        System.out.println("…………(post-processing后处理,收尾工作,可添加代码)");
    }
    
    private void check(){
        System.out.println("【check()函数】:对query进行Pre-Processing前处理,检查权限");
    }
}

然后,我们在Spring的配置文件里面,将整个流程都统一起来。
文件beans.xml
<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans"
       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">

    <bean id="checkClass" class="aop.CheckClass"></bean>
    <bean id="queryClass" class="aop.QueryClass"></bean>
    <!--
        定义正则表达式,来规定如何匹配,即匹配哪些方法,要求这些方法做前处理、后处理
        需要学习如何使用这里的正则。我们来看.*query[0-9]+
        .*     代表匹配任意多个字符,点代表匹配字符,星号代表0~无穷个
        query  自然就是匹配这个query字段了
        [0-9]* 代表匹配0~无穷个数字
    -->
    <bean id="queryPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
        <property name="pattern" value=".*query[0-9]+"/>
    </bean>
    <!--
        这个是interceptor(拦截者)的bean里面定义了
        切入点(匹配哪些方法进行前后处理):queryPointcut
        切入的东西(前后处理的方法由哪个类来执行):checkClass
    -->
    <bean id="interceptorCheckClass" class="org.springframework.aop.support.DefaultPointcutAdvisor">
        <property name="advice" ref="checkClass"/>
        <property name="pointcut" ref="queryPointcut"/>
    </bean>
    <bean id="queryProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!--
            根据QueryInterface生成的目标类设置为QueryClass
            则目标target设置为:queryClass
            则代理interface为:aop.QueryInterface
            则拦截者interceptor为:
        -->
        <property name="target" ref="queryClass"/>
        <property name="interceptorNames" value="interceptorCheckClass" />
        <property name="proxyInterfaces" value="aop.QueryInterface" />
    </bean>
</beans>

最后,我们在main函数里面运行代码:
文件MainClass.java
package Main;

import aop.QueryInterface;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainClass {

    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("configuration/beans.xml");
        QueryInterface qi = (QueryInterface)ctx.getBean("queryProxy");
        qi.query1();
        qi.query2();
        qi.query3();
        qi.queryN();
        qi.query4();
    }
}

运行结果如下:
Spring中AOP,一个query与check的实现(二)——详细完整Java代码实现

  从结果我们可以看到,方法queryN由于不符合正则表达式的匹配,所以并没有运行前处理程序和后处理程序。如果我们把queryN的方法名改成query999,那么它就会被匹配,激发前后处理函数运行。


参考资料:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值