一个目标类对应多个切面的例子

来源:互联网 发布:服装销售软件排行 编辑:程序博客网 时间:2024/06/06 04:52

在之前的cglib代理原理中(至于cglib和jdk代理的区别,看之前的博文),我们涉及到了多个切面,但是那时候说的切面,还不算真正意义上的切面(没有在spring配置文件中配置)。现在我修改一个那个例子.


需求:

我们仍然查询某一个人的薪水


需求分析:

我们直接通过目标类来查询某个人的薪水,但是在我们通过调用目标方法的时候,有各种通知在运作,就像拦截器一样,如果没有相应的权限的话,就不给查询。


通知的分析:

在以前的例子中,我们用到了3个切面,分别是privilege(权限),security(安全性框架),logger(日志),当时由于我们还没有学通知的概念,所以只是调用了一下其中的方法而已,现在我们要区分一下它们对应的方法分别属于什么通知。

日志切面和安全性框架切面对于用户的权限没有要求,只要你发送了这个请求,就要经过相应的通知,所以日志和安全性框架属于前置通知。

权限切面是需要在经过了前置通知之后,然后再判断是否满足相应的条件来决定是否让客户端执行目标方法,所以权限切面的方法属于环绕通知。

代码实现:

以下是切面的定义:

//日志切面public class Logger {    public void logging(){        System.out.println("logging");    }}   //安全性框架切面:public class Security {    public void security(){        System.out.println("security");    }}//权限切面public class Privilege {    //设置一个变量,并且设置其getter&setter方法,这样就可以在配置文件中赋值    private String access;    /**     * 判断用户是否为admin,如果不是,就不给查询     * @param joinPoint     * @throws Throwable     */    public void isAccess(ProceedingJoinPoint joinPoint) throws Throwable{        if("admin".equals(access)){            //允许客户端调用目标方法            joinPoint.proceed();        }else{            //抛出没有相应权限的异常            throw new RuntimeException("you have no privilege to pull this request");        }    }    //getter&setter方法,如果没有这个方法,会报错    public String getAccess() {        return access;    }    public void setAccess(String access) {        this.access = access;    }}//下面是目标类:public class SalaryManager {    public void showSalary(){        System.out.println("show salary");    }}

以下是配置文件的配置:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:aop="http://www.springframework.org/schema/aop" 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/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">     <!--         把要用到的切面以及目标类配置到配置文件中      -->          <bean id="logger" class="cn.ansel.oneTarget2ManyAspects.Logger"></bean>    <bean id="security" class="cn.ansel.oneTarget2ManyAspects.Security"></bean>    <!--         为privilege类中的access属性赋值     -->    <bean id="privilege" class="cn.ansel.oneTarget2ManyAspects.Privilege">        <property name="access" value=""admin""></property>    </bean>    <bean id="salaryManager" class="cn.ansel.oneTarget2ManyAspects.SalaryManager"></bean>    <aop:config>        <!--             设置切入点表达式         -->        <aop:pointcut expression="execution(* cn.ansel.oneTarget2ManyAspects.SalaryManager.*(..))" id="perform"/>        <!--             有几个切面就要定义几个aop:aspect 并且把ref的值设置好         -->        <aop:aspect ref="logger">            <aop:before method="logging" pointcut-ref="perform"/>        </aop:aspect>        <aop:aspect ref="security">            <aop:before method="security" pointcut-ref="perform"/>        </aop:aspect>        <!--             在这里设置好环绕通知,         -->        <aop:aspect ref="privilege">            <aop:around method="isAccess" pointcut-ref="perform"/>        </aop:aspect>    </aop:config></beans>
//以下是测试类的代码:public class testOne2Many {    @Test    public void test(){        //开启spring容器        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("cn/ansel/oneTarget2ManyAspects/applicationContext.xml");        //使用cglib代理得到目标类的代理对象        SalaryManager cglibProxy=(SalaryManager) applicationContext.getBean("salaryManager");        //调用目标方法        cglibProxy.showSalary();    }}

运行结果:
这里写图片描述
当我们把配置文件中access的值改成其他值的时候

<property name="access" value="asd"></property>

再运行测试类:
这里写图片描述
异常:
这里写图片描述

0 0
原创粉丝点击