相关阅读
简介
Joinpoint 表示通用的运行时连接点; 运行时连接点是发生在静态连接点上的事件,比如方法的一次调用就是运行时连接点;可以通过getStaticPart 获取连接点的静态部分; 在拦截框架的上下文中,运行时连接点是可访问的对象(方法,构造方法,字段),即连接点的静态部分,的访问的物化,被传递给注册在静态连接点上的拦截器;
源码
public interface Joinpoint {
@Nullable
Object proceed() throws Throwable;
@Nullable
Object getThis();
@Nonnull
AccessibleObject getStaticPart();
}
实现子类
public interface Joinpoint
public interface Invocation extends Joinpoint
public interface ConstructorInvocation extends Invocation
public interface MethodInvocation extends Invocation
public interface ProxyMethodInvocation extends MethodInvocation
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable
private static class CglibMethodInvocation extends ReflectiveMethodInvocation
Invocation
简介
Invocation 代表一次调用; Invocation 可以被Interceptor 拦截;
核心代码
public interface Invocation extends Joinpoint {
@Nonnull
Object[] getArguments();
}
ConstructorInvocation
简介
ConstructorInvocation 代表构造方法的调用,在构造方法调用时提供给拦截器; ConstructorInvocation 可以被ConstructorInterceptor 拦截;
核心代码
public interface ConstructorInvocation extends Invocation {
@Nonnull
Constructor<?> getConstructor();
}
MethodInvocation
简介
MethodInvocation 代表方法的调用,在方法调用时提供给拦截器; MethodInvocation 可以被MethodInterceptor 拦截;
核心代码
public interface MethodInvocation extends Invocation {
@Nonnull
Method getMethod();
}
ProxyMethodInvocation
简介
ProxyMethodInvocation 支持访问通过该方法调用的代理对象; 当需要替换返回值为代理对象时,这很有用,比如方法的返回值就是目标对象本身;
核心代码
public interface ProxyMethodInvocation extends MethodInvocation {
Object getProxy();
MethodInvocation invocableClone();
MethodInvocation invocableClone(Object... arguments);
void setArguments(Object... arguments);
void setUserAttribute(String key, @Nullable Object value);
@Nullable
Object getUserAttribute(String key);
}
ProxyMethodInvocation
简介
ProxyMethodInvocation 支持访问通过该方法调用的代理对象; 当需要替换返回值为代理对象时,这很有用,比如方法的返回值就是目标对象本身;
核心代码
public interface ProxyMethodInvocation extends MethodInvocation {
Object getProxy();
MethodInvocation invocableClone();
MethodInvocation invocableClone(Object... arguments);
void setArguments(Object... arguments);
void setUserAttribute(String key, @Nullable Object value);
@Nullable
Object getUserAttribute(String key);
}
ReflectiveMethodInvocation
简介
Spring框架的MethodInvocation 实现,通过反射 调用目标对象,子类可以重写invokeJoinpoint 方法来实现其它的逻辑; 可以通过invocableClone 克隆一次方法调用来重复执行proceed ,也可以通过setUserAttribute /getUserAttribute 绑定一些定制属性到方法调用;
核心代码
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {
protected final Object proxy;
@Nullable
protected final Object target;
protected final Method method;
protected Object[] arguments;
@Nullable
private final Class<?> targetClass;
@Nullable
private Map<String, Object> userAttributes;
protected final List<?> interceptorsAndDynamicMethodMatchers;
private int currentInterceptorIndex = -1;
protected ReflectiveMethodInvocation(
Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments,
@Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {
this.proxy = proxy;
this.target = target;
this.targetClass = targetClass;
this.method = BridgeMethodResolver.findBridgedMethod(method);
this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
}
@Override
public final Object getProxy() {
return this.proxy;
}
@Override
@Nullable
public final Object getThis() {
return this.target;
}
@Override
public final AccessibleObject getStaticPart() {
return this.method;
}
@Override
public final Method getMethod() {
return this.method;
}
@Override
public final Object[] getArguments() {
return this.arguments;
}
@Override
public void setArguments(Object... arguments) {
this.arguments = arguments;
}
@Override
@Nullable
public Object proceed() throws Throwable {
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
return proceed();
}
}
else {
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
@Nullable
protected Object invokeJoinpoint() throws Throwable {
return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}
@Override
public MethodInvocation invocableClone() {
Object[] cloneArguments = this.arguments;
if (this.arguments.length > 0) {
cloneArguments = this.arguments.clone();
}
return invocableClone(cloneArguments);
}
@Override
public MethodInvocation invocableClone(Object... arguments) {
if (this.userAttributes == null) {
this.userAttributes = new HashMap<>();
}
try {
ReflectiveMethodInvocation clone = (ReflectiveMethodInvocation) clone();
clone.arguments = arguments;
return clone;
}
catch (CloneNotSupportedException ex) {
throw new IllegalStateException(
"Should be able to clone object of type [" + getClass() + "]: " + ex);
}
}
@Override
public void setUserAttribute(String key, @Nullable Object value) {
if (value != null) {
if (this.userAttributes == null) {
this.userAttributes = new HashMap<>();
}
this.userAttributes.put(key, value);
}
else {
if (this.userAttributes != null) {
this.userAttributes.remove(key);
}
}
}
@Override
@Nullable
public Object getUserAttribute(String key) {
return (this.userAttributes != null ? this.userAttributes.get(key) : null);
}
public Map<String, Object> getUserAttributes() {
if (this.userAttributes == null) {
this.userAttributes = new HashMap<>();
}
return this.userAttributes;
}
}
CglibMethodInvocation
简介
AOP代理使用的MethodInvocation 实现;
核心代码
private static class CglibMethodInvocation extends ReflectiveMethodInvocation {
@Nullable
private final MethodProxy methodProxy;
public CglibMethodInvocation(Object proxy, @Nullable Object target, Method method,
Object[] arguments, @Nullable Class<?> targetClass,
List<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {
super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);
this.methodProxy = (isMethodProxyCompatible(method) ? methodProxy : null);
}
@Override
@Nullable
public Object proceed() throws Throwable {
try {
return super.proceed();
}
catch (RuntimeException ex) {
throw ex;
}
catch (Exception ex) {
if (ReflectionUtils.declaresException(getMethod(), ex.getClass()) ||
KotlinDetector.isKotlinType(getMethod().getDeclaringClass())) {
throw ex;
}
else {
throw new UndeclaredThrowableException(ex);
}
}
}
@Override
protected Object invokeJoinpoint() throws Throwable {
if (this.methodProxy != null) {
try {
return this.methodProxy.invoke(this.target, this.arguments);
}
catch (CodeGenerationException ex) {
logFastClassGenerationFailure(this.method);
}
}
return super.invokeJoinpoint();
}
static boolean isMethodProxyCompatible(Method method) {
return (Modifier.isPublic(method.getModifiers()) &&
method.getDeclaringClass() != Object.class && !AopUtils.isEqualsMethod(method) &&
!AopUtils.isHashCodeMethod(method) && !AopUtils.isToStringMethod(method));
}
}
|