Spring AOP使用Aspectj基於xml方式,初始化Bean引數
阿新 • • 發佈:2019-02-11
場景:
大多數實體繼承了一個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