📄 cglib2aopproxy.java
字号:
// Now copy both the callbacks from mainCallbacks
// and fixedCallbacks into the callbacks array.
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
for (int x = 0; x < mainCallbacks.length; x++) {
callbacks[x] = mainCallbacks[x];
}
for (int x = 0; x < fixedCallbacks.length; x++) {
callbacks[x + mainCallbacks.length] = fixedCallbacks[x];
}
this.fixedInterceptorOffset = mainCallbacks.length;
}
else {
callbacks = mainCallbacks;
}
return callbacks;
}
/**
* Wrap a return of this if necessary to be the proxy
*/
private static Object massageReturnTypeIfNecessary(Object proxy, Object target, Object retVal) {
// Massage return value if necessary
if (retVal != null && retVal == target) {
// Special case: it returned "this"
// Note that we can't help if the target sets a reference
// to itself in another returned object.
retVal = proxy;
}
return retVal;
}
public int hashCode() {
return 0;
}
/**
* Checks to see if this CallbackFilter is the same CallbackFilter used for
* another proxy.
*/
public boolean equals(Object other) {
if (other == null) {
return false;
}
if (other == this) {
return true;
}
Cglib2AopProxy otherCglibProxy = null;
if (other instanceof Cglib2AopProxy) {
otherCglibProxy = (Cglib2AopProxy) other;
}
else {
// not a valid comparison
return false;
}
return AopProxyUtils.equalsInProxy(advised, otherCglibProxy.advised);
}
/**
* Serializable replacement for CGLIB's NoOp interface.
* Public to allow use elsewhere in the framework.
*/
public static class SerializableNoOp implements NoOp, Serializable {
}
/**
* Method interceptor used for static targets with no advice chain. The call
* is passed directly back to the target. Used when the proxy needs to be
* exposed and it can't be determined that the method won't return
* <code>this</code>.
*/
private static class StaticUnadvisedInterceptor implements MethodInterceptor, Serializable {
private final Object target;
public StaticUnadvisedInterceptor(Object target) {
this.target = target;
}
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
Object retVal = methodProxy.invoke(target, args);
return massageReturnTypeIfNecessary(proxy, target, retVal);
}
}
/**
* Method interceptor used for static targets with no advice chain, when the
* proxy is to be exposed.
*/
private static class StaticUnadvisedExposedInterceptor implements MethodInterceptor, Serializable {
private final Object target;
public StaticUnadvisedExposedInterceptor(Object target) {
this.target = target;
}
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
try {
oldProxy = AopContext.setCurrentProxy(proxy);
Object retVal = methodProxy.invoke(target, args);
return massageReturnTypeIfNecessary(proxy, target, retVal);
}
finally {
AopContext.setCurrentProxy(oldProxy);
}
}
}
/**
* Interceptor used to invoke a dynamic target without creating a method
* invocation or evaluating an advice chain. (We know there was no advice
* for this method.)
*/
private class DynamicUnadvisedInterceptor implements MethodInterceptor, Serializable {
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
Object target = advised.getTargetSource().getTarget();
try {
Object retVal = methodProxy.invoke(target, args);
return massageReturnTypeIfNecessary(proxy, target, retVal);
}
finally {
advised.getTargetSource().releaseTarget(target);
}
}
}
/**
* Interceptor for unadvised dynamic targets when the proxy needs exposing.
*/
private class DynamicUnadvisedExposedInterceptor implements MethodInterceptor, Serializable {
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
Object target = advised.getTargetSource().getTarget();
try {
oldProxy = AopContext.setCurrentProxy(proxy);
Object retVal = methodProxy.invoke(target, args);
return massageReturnTypeIfNecessary(proxy, target, retVal);
}
finally {
AopContext.setCurrentProxy(oldProxy);
advised.getTargetSource().releaseTarget(target);
}
}
}
/**
* Dispatcher for a static target. Dispatcher is much faster than
* interceptor. This will be used whenever it can be determined that a
* method definitely does not return "this"
*/
private static class StaticDispatcher implements Dispatcher, Serializable {
private Object target;
public StaticDispatcher(Object target) {
this.target = target;
}
public Object loadObject() {
return target;
}
}
/**
* Dispatcher for any methods declared on the Advised class.
*/
private class AdvisedDispatcher implements Dispatcher, Serializable {
public Object loadObject() throws Exception {
return advised;
}
}
/**
* Dispatcher for the equals() method. Ensures that the method call is
* always handled by this class.
*/
private static class EqualsInterceptor implements MethodInterceptor, Serializable {
private final AdvisedSupport advised;
public EqualsInterceptor(AdvisedSupport advised) {
this.advised = advised;
}
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
Object other = args[0];
if (other == null) {
return Boolean.FALSE;
}
if (other == proxy) {
return Boolean.TRUE;
}
AdvisedSupport otherAdvised = null;
if (other instanceof Factory) {
Callback callback = ((Factory) other).getCallback(INVOKE_EQUALS);
if (!(callback instanceof EqualsInterceptor)) {
return Boolean.FALSE;
}
otherAdvised = ((EqualsInterceptor) callback).advised;
}
else {
// not a valid comparison
return Boolean.FALSE;
}
return (AopProxyUtils.equalsInProxy(this.advised, otherAdvised) ? Boolean.TRUE : Boolean.FALSE);
}
}
/**
* Interceptor used specifcally for advised methods on a frozen, static proxy.
*/
private static class FixedChainStaticTargetInterceptor implements MethodInterceptor, Serializable {
private final List adviceChain;
private final Object target;
private final Class targetClass;
public FixedChainStaticTargetInterceptor(List adviceChain, Object target, Class targetClass) {
this.adviceChain = adviceChain;
this.target = target;
this.targetClass = targetClass;
}
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object retVal = null;
MethodInvocation invocation = new CglibMethodInvocation(proxy, this.target, method, args,
this.targetClass, this.adviceChain, methodProxy);
// If we get here, we need to create a MethodInvocation.
retVal = invocation.proceed();
retVal = massageReturnTypeIfNecessary(proxy, this.target, retVal);
return retVal;
}
}
/**
* General purpose AOP callback. Used when the target is dynamic or when the
* proxy is not frozen.
*/
private class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
MethodInvocation invocation = null;
Object oldProxy = null;
boolean setProxyContext = false;
Class targetClass = null; //targetSource.getTargetClass();
Object target = null;
try {
Object retVal = null;
if (advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// May be <code>null</code>. Get as late as possible to minimize the time we
// "own" the target, in case it comes from a pool.
target = getTarget();
if (target != null) {
targetClass = target.getClass();
}
List chain = advised.getAdvisorChainFactory()
.getInterceptorsAndDynamicInterceptionAdvice(advised, proxy, method, targetClass);
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -