通过反射获取spring中aop代理的target对象
2020-04-09 本文已影响0人
人才辈出玫瑰班
最近项目需要获取从spring创建的aop代理中获取它的target对象,其实可以通过反射来获取,代码如下
public class ProxyUtil {
// CglibAopProxy
public static Object getCglibProxyTargetObject(Object proxy) throws Exception {
Field h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0");
h.setAccessible(true);
Object dynamicAdvisedInterceptor = h.get(proxy);
Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised");
advised.setAccessible(true);
return ((AdvisedSupport) advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget();
}
// JdkDynamicAopProxy
public static Object getJdkDynamicProxyTargetObject(Object proxy) throws Exception {
Field h = proxy.getClass().getSuperclass().getDeclaredField("h");
h.setAccessible(true);
AopProxy aopProxy = (AopProxy) h.get(proxy);
Field advised = aopProxy.getClass().getDeclaredField("advised");
advised.setAccessible(true);
return ((AdvisedSupport) advised.get(aopProxy)).getTargetSource().getTarget();
}
}
aop的实现一般分为cglib代理和jdk代理,所以在获取spring中某个aop代理的target时,需要先判断是属于那个实现,进而选用对应的获取方式
通过这一步,我们解决了上一篇《当springsecurity的remember-me功能遇上用户名修改》无法通过 RememberMeServices 转化为 PersistentTokenBasedRememberMeServices 进而在创建新的token之前删除旧的token的问题
@Autowired
@Lazy
private RememberMeServices rememberMeService;
private volatile PersistentTokenBasedRememberMeServices persistentRememberMeServices;
// 刷新authentication和cookie
private void refreshAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication oldAuthentication) {
if(checkCookie(request)){
// 先删除就的token然后创建新的token
getPersistentTokenBasedRememberMeServices().logout(request,response,oldAuthentication);
rememberMeService.loginSuccess(request, response, getAuthentication());
}
}
// 单例-加锁
private PersistentTokenBasedRememberMeServices getPersistentTokenBasedRememberMeServices() {
if(persistentTokenBasedRememberMeServices == null){
synchronized (this){
if(persistentTokenBasedRememberMeServices == null) {
try {
persistentTokenBasedRememberMeServices =
(PersistentTokenBasedRememberMeServices) ProxyUtil.getJdkDynamicProxyTargetObject(rememberMeService);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return persistentTokenBasedRememberMeServices;
}