场景:
大多数实体继承了一个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
,而在拦截Controller
和Service
的时候spring对切点的配置是有一些不一样的,关于Spring在字节码增强的方面,笔者刚接触Spring不久,现在恐怕还没能力解释什么,这里不多说,免得误导了大家。有很多前辈已经给我们指明了前路,感兴趣的可以自行百度。
学生浅薄,望众师指点
wengang.liu