此執行個體為,使用Spring切面,将接口的部分方法替換為其他執行個體的同名同參方法
每一個接口類建立對應一個RPC Client的使用,業務場景為對特定辨別使用者,使用新的RPC Client的部分方法。
AOP 代理
Spring AOP 預設将标準
JDK動态代理
用于 AOP 代理。這使得可以代理任何接口(或一組接口)。
Spring AOP 也可以使用
CGLIB
代理。這對于代理類而不是接口是必需的。如果業務對象未實作接口,則預設情況下使用
CGLIB
。最好的做法是對接口進行程式設計,而不是對類進行程式設計。業務類通常将實作一個或多個業務接口。在某些情況下(可能極少發生),您需要建議未在接口上聲明的方法,或者需要将代理對象作為具體類型傳遞給方法,則可以使用強制使用CGLIB。
重要的是要掌握 Spring AOP 是基于“代理”的事實。有關此實作細節實際含義的徹底檢查,請參見了解AOP代理。
設計思路
- 使用Spring Aspcct Around切面,切點為原接口的所有方法
- 在對應配置的方法,對特定辨別使用者替換為新接口
- 通過新接口的執行個體及方法,動态代理生成結果
代碼實作
将
ShareService
的
batchGetShare()
及
listShare()
,對特定辨別使用者替換為
ShareProxyService
的實作
@Aspect
@Component
public class ShareProxyAspect {
private static Logger logger = LoggerFactory.getLogger(ShareProxyAspect.class);
@Autowired
private ShareProxyService shareProxyService;
@Autowired
private IdentityService identityService;
private static List<String> proxyMethodName = Lists.newArrayList(
"batchGetShare",
"listShare"
);
/**
* 攔截ShareService
*/
@Around(value = "execution(* com.example.api.ShareService.*(..))")
public Object shareProxy(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
try {
Object[] args = proceedingJoinPoint.getArgs();
MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
Method method = signature.getMethod();
String methodName = method.getName();
if (proxyMethodName.contains(methodName)) {
String uid = UserContext.getLoginUid();
if (identityService.getIdentityFlag(uid)) {
Method[] methods = shareProxyService.getClass().getMethods();
Method proxyMethod = getMethodByName(methods, methodName);
logger.info("ShareProxyAspect invoke,uid={} method={} args={}", uid, methodName, args);
return proxyMethod.invoke(moneyShareProxyService, args);
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
}
private Method getMethodByName(Method[] methods, String methodName) {
for (Method method : methods) {
if (method.getName().equals(methodName)) {
return method;
}
}
// ShareProxyService拓展方法保證不會出現空
return null;
}
}