Spring AOP及MethodInterceptor拦截器实现方法拦截以及切入点函数阻止执行

 

声明:本博文用于学习总结及工作心得

 

 

 

项目中需要修改IM信息送以及短信发送,要求已离职的人员不呢收到IM信息和短信

 

因为在项目中各个地方都有使用到短信和IM信息通知;所以想到使用Spring AOP进行实现,以及拦截器进行实现,一下为两种方法的具体实现代码:
1)Spsing AOP

 

 

需要被织入的切面类:
ppackage com.xxx.utils;


import com.xxx.bean_new.personnel.Employee;
import com.xxx.bean_new.personnel.User;
import com.xxx.dao_new.EmployeeDAO;
import com.xxx.dao_new.UserDAO;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;


/**
 * Created by Administrator on 2016/11/4 0004.
 */
//声明这是一个切面Bean
@Aspect
public class SendMsgAspect {
    @Before("execution(* com.xxx.pushMsg.PushMsg.sendMsg(..))")
    Object before(JoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        try {
            if (args.length >= 2) {
                String IMAccount = (String) args[2];
                UserDAO userDAO = (UserDAO) Utils.getBean("userDAO");
                if (null != userDAO) {
                    User user = userDAO.getUsersByIMAccount(IMAccount);
                    if (null != user) {
                        EmployeeDAO employeeDAO = (EmployeeDAO) Utils.getBean("employeeDAO");
                        Employee employee = employeeDAO.get(user.getEmployeeId());
//这里进行业务逻辑判断 通过IMAcount信息获取到员工,如果该员工状态为离职,则将IMAcount修改空也就是args[2];并且抛出异常 由try{}catch捕捉该异常
//否则不做任何操作,直接返回

                        if (employee == null || employee.getEntry() == null || employee.getEntry().getStatus() == null || "离职".equals(employee.getEntry().getStatus())) {
                            args[2] = "";
                            throw new RuntimeException(employee.getName() + ":该员工已离职通知失败!");

                        }
                    }
                }
            }
        } catch (Exception e) {
     //扑捉到异常后 pjp.proceed(args)将args 也就是修改后的参数传给目标函数 这里的目标函数是指被切入点的函数
             //需要注意的是,如果是使用了pjp.proceed(args) 目标函数会被执行两次 正是因为这点 所以接着写了另一个具有相同功能的拦截器

            ProceedingJoinPoint pjp = (ProceedingJoinPoint) joinPoint;
            Object retVal = null;
            try {
                retVal = pjp.proceed(args);
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
            return retVal;

        }
        return null;
    }
}

 

applicationContext.xml配置文件修改
配置文件中添加以下内容:


<bean id="sendMsgAop" class="com.xxx.utils.SendMsgAspect">
</bean>
<aop:config>
<!-- 定义切点 -->
<aop:pointcut id="aroundPointcutTarget"
 expression="execution(* com.xxx.pushMsg.PushMsg.sendMsg(..))"/>
<!-- 定义切面 -->
<aop:aspect id="userAspect" ref="sendMsgAop">
<!--通知函数 method 的参数为 ProceedingJoinPoint 类型 该类型为 JoinPoint 的子类 可以通过该对象获取 被切面参数 以及 返回值-->
<aop:before method="before" pointcut-ref="aroundPointcutTarget"/>
<!--<aop:around method="checkEntrystatus" pointcut-ref="aroundPointcutTarget"/>-->
</aop:aspect>
</aop:config>

 

 

 

 

 

2)MethodInterceptor拦截器

 

拦截器类
package com.xxx.utils;


import com.xxx.bean_new.personnel.Employee;
import com.xxx.bean_new.personnel.User;
import com.xxx.dao_new.EmployeeDAO;
import com.xxx.dao_new.UserDAO;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;


import java.lang.reflect.Method;


/**
 * Created by Administrator on 2016/11/5 0005.
 */
public class SendMsgInterceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invo) throws Throwable {
        Object[] args = invo.getArguments();
        Method method = invo.getMethod();
        if (!"sendMsg".equals(method.getName())) {
            Object obj = invo.proceed();
            return obj;
        }
        try {
            if (args.length >= 2) {
                String IMAccount = (String) args[2];
                UserDAO userDAO = (UserDAO) Utils.getBean("userDAO");
                if (null != userDAO) {
                    User user = userDAO.getUsersByIMAccount(IMAccount);
                    if (null != user) {
                        EmployeeDAO employeeDAO = (EmployeeDAO) Utils.getBean("employeeDAO");
                        Employee employee = employeeDAO.get(user.getEmployeeId());
//业务逻辑判断 通过IMAcount信息获取到员工,如果该员工状态不为离职的情况下,通过 invo.proceed();它来对目标对象方法调用,返回一个Object对象。
//否则不做任何操作,直接返回

                        if (employee != null && employee.getEntry() != null && employee.getEntry().getStatus() != null && !"".equals(employee.getEntry().getStatus())) {
                            Object obj = invo.proceed();
                            return obj;
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return args;
    }
}
applicationContext.xml配置文件修改
<bean id="myInterceptor"
 class="com.xxx.utils.SendMsgInterceptor"
 abstract="false" lazy-init="default"
 autowire="default">
</bean>

<!--这里需要注意如果是使用接口的话 这里需要这样定义-->
<!--<bean id="bean" class="org.springframework.aop.framework.ProxyFactoryBean">  
        <property name="proxyInterfaces">  
            <value>aop.Interface</value>  
        </property>
<property name="interceptorNames">
<list>
<value>myInterceptor</value>
</list>
</property>
</bean>-->


<!--方法-->
<!--<bean class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">-->
<!--<property name="mappedNames">-->
<!--<list>-->
<!--<value>send*</value>&lt;!&ndash; 所有方法 &ndash;&gt;-->
<!--</list>-->
<!--</property>-->
<!--<property name="advice">-->
<!--<ref local="myInterceptor"/>-->
<!--</property>-->
<!--</bean>-->


<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<!--PushMsg类可以使用注解 或者手动加入到配置文件-->
<list><value>pushMsg</value></list>
</property>
<property name="interceptorNames">
<list>
<value>myInterceptor</value>
</list>
</property>
</bean>

 

第二种不会造成目标函数第二次执行

 

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值