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

来源:互联网 发布:ruby python 比较 编辑:程序博客网 时间:2024/05/19 16:33

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



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

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

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


import com.rhxy.bean_new.personnel.Employee;
import com.rhxy.bean_new.personnel.User;
import com.rhxy.dao_new.EmployeeDAO;
import com.rhxy.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.rhxy.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.rhxy.utils.SendMsgAspect">
</bean>
<aop:config>
<!-- 定义切点 -->
<aop:pointcut id="aroundPointcutTarget"
 expression="execution(* com.rhxy.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.rhxy.utils;


import com.rhxy.bean_new.personnel.Employee;
import com.rhxy.bean_new.personnel.User;
import com.rhxy.dao_new.EmployeeDAO;
import com.rhxy.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.rhxy.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 0
原创粉丝点击