Spring AOP使用Aspectj基于xml方式,初始化Bean参数

场景:

大多数实体继承了一个BaseBean,这里所做的就是使用Spring的Aop功能实现,拦截到的方法,对其参数做一些处理。


spring-xxx.xml的核心配置:

    <aop:aspectj-autoproxy proxy-target-class="true" />

    <aop:config>
       <!--配置com.xxx.xxx.*.controller包下所有类或接口的所有方法-->
       <aop:pointcut id="businessService" expression="execution(* com.xxx.xxx.*.controller.*.*(..))" />
       <aop:aspect id="TestAspect" ref="aspectBean">
           <aop:before pointcut-ref="businessService" method="doBefore"/>
           <aop:after pointcut-ref="businessService" method="doAfter"/>
           <aop:after-throwing pointcut-ref="businessService" method="doThrowing" throwing="ex"/>
       </aop:aspect>
    </aop:config>

    <bean id="aspectBean" class="com.xxx.xxx.common.TestAspect" />

切点类:

package com.xxx.xxx.common;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.aspectj.lang.JoinPoint;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.xxx.xxx.bean.BaseBean;
import com.xxx.xxx.bean.LoginUser;

public class TestAspect {

    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(TestAspect.class);

    public void doAfter(JoinPoint jp) {

        LOGGER.debug("log Ending method: " + jp.getTarget().getClass().getName() + "." + jp.getSignature().getName());

    }

    public void doBefore(JoinPoint jp) throws Exception {

        Object[] args = jp.getArgs();
        for (Object object : args) {
            // 判断获取的参数对象是不是继承了BaseBean
            if (BaseBean.class.isAssignableFrom(object.getClass())) {
                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
                HttpSession httpSession = request.getSession();
                if (httpSession == null) {
                    LOGGER.error("获取session失败");
                }
                LoginUser loginUser = (LoginUser) httpSession.getAttribute(Constants.LOGIN_USER);
                Class father = httpSession.getAttribute(Constants.LOGIN_USER).getClass().getSuperclass();
                try {
                    // 获取父类setLoginBean方法
                    Method method = father.getMethod("setLoginBean", new Class[] { LoginUser.class });
                    // 使用反射机制可以打破封装性,导致了java对象的属性不安全
                    // method.setAccessible(true);
                    // 反射调用父类方法
                    method.invoke(object, new Object[] { loginUser });
                } catch (Exception e) {
                    LOGGER.error(e.getStackTrace() + ":" + e.getMessage());
                }
            }
        }

        LOGGER.debug("log Begining method: " + jp.getTarget().getClass().getName() + "." + jp.getSignature().getName() + "[PARAMS]:" + jp.getArgs().toString());

    }

    public void doThrowing(JoinPoint jp, Throwable ex) {
        LOGGER.error("method " + jp.getTarget().getClass().getName() + "." + jp.getSignature().getName() + " throw exception");
        LOGGER.error(ex.getStackTrace() + ":" + ex.getMessage());
    }
}

注:这里拦截的类是Controller,并非Service,而在拦截ControllerService的时候spring对切点的配置是有一些不一样的,关于Spring在字节码增强的方面,笔者刚接触Spring不久,现在恐怕还没能力解释什么,这里不多说,免得误导了大家。有很多前辈已经给我们指明了前路,感兴趣的可以自行百度。

学生浅薄,望众师指点

wengang.liu
学生浅薄 望众师指点
原文地址:https://www.cnblogs.com/Nihility/p/14695673.html