Spring学习心得(19)-- 一个目标类对应多个切面的例子

在之前的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>
 
 
  • 1
  • 1

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





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值