You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
/* * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */packageorg.springframework.aop.framework;
importjava.io.Serializable;
importjava.lang.reflect.InvocationHandler;
importjava.lang.reflect.Method;
importjava.lang.reflect.Proxy;
importjava.util.List;
importorg.aopalliance.intercept.MethodInvocation;
importorg.apache.commons.logging.Log;
importorg.apache.commons.logging.LogFactory;
importorg.springframework.aop.AopInvocationException;
importorg.springframework.aop.RawTargetAccess;
importorg.springframework.aop.TargetSource;
importorg.springframework.aop.support.AopUtils;
importorg.springframework.core.DecoratingProxy;
importorg.springframework.util.Assert;
importorg.springframework.util.ClassUtils;
/** * JDK-based {@link AopProxy} implementation for the Spring AOP framework, * based on JDK {@link java.lang.reflect.Proxy dynamic proxies}. * * <p>Creates a dynamic proxy, implementing the interfaces exposed by * the AopProxy. Dynamic proxies <i>cannot</i> be used to proxy methods * defined in classes, rather than interfaces. * * <p>Objects of this type should be obtained through proxy factories, * configured by an {@link AdvisedSupport} class. This class is internal * to Spring's AOP framework and need not be used directly by client code. * * <p>Proxies created using this class will be thread-safe if the * underlying (target) class is thread-safe. * * <p>Proxies are serializable so long as all Advisors (including Advices * and Pointcuts) and the TargetSource are serializable. * * @author Rod Johnson * @author Juergen Hoeller * @author Rob Harrop * @author Dave Syer * @see java.lang.reflect.Proxy * @see AdvisedSupport * @see ProxyFactory */finalclassJdkDynamicAopProxyimplementsAopProxy, InvocationHandler, Serializable {
/** use serialVersionUID from Spring 1.2 for interoperability */privatestaticfinallongserialVersionUID = 5531744639992436476L;
/* * NOTE: We could avoid the code duplication between this class and the CGLIB * proxies by refactoring "invoke" into a template method. However, this approach * adds at least 10% performance overhead versus a copy-paste solution, so we sacrifice * elegance for performance. (We have a good test suite to ensure that the different * proxies behave the same :-) * This way, we can also more easily take advantage of minor optimizations in each class. *//** We use a static Log to avoid serialization issues */privatestaticfinalLoglogger = LogFactory.getLog(JdkDynamicAopProxy.class);
/** Config used to configure this proxy */privatefinalAdvisedSupportadvised;
/** * Is the {@link #equals} method defined on the proxied interfaces? */privatebooleanequalsDefined;
/** * Is the {@link #hashCode} method defined on the proxied interfaces? */privatebooleanhashCodeDefined;
/** * Construct a new JdkDynamicAopProxy for the given AOP configuration. * @param config the AOP configuration as AdvisedSupport object * @throws AopConfigException if the config is invalid. We try to throw an informative * exception in this case, rather than let a mysterious failure happen later. */publicJdkDynamicAopProxy(AdvisedSupportconfig) throwsAopConfigException {
Assert.notNull(config, "AdvisedSupport must not be null");
if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
thrownewAopConfigException("No advisors and no TargetSource specified");
}
this.advised = config;
}
@OverridepublicObjectgetProxy() {
returngetProxy(ClassUtils.getDefaultClassLoader());
}
@OverridepublicObjectgetProxy(ClassLoaderclassLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
returnProxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
/** * Finds any {@link #equals} or {@link #hashCode} method that may be defined * on the supplied set of interfaces. * @param proxiedInterfaces the interfaces to introspect */privatevoidfindDefinedEqualsAndHashCodeMethods(Class<?>[] proxiedInterfaces) {
for (Class<?> proxiedInterface : proxiedInterfaces) {
Method[] methods = proxiedInterface.getDeclaredMethods();
for (Methodmethod : methods) {
if (AopUtils.isEqualsMethod(method)) {
this.equalsDefined = true;
}
if (AopUtils.isHashCodeMethod(method)) {
this.hashCodeDefined = true;
}
if (this.equalsDefined && this.hashCodeDefined) {
return;
}
}
}
}
/** * Implementation of {@code InvocationHandler.invoke}. * <p>Callers will see exactly the exception thrown by the target, * unless a hook method throws an exception. */@OverridepublicObjectinvoke(Objectproxy, Methodmethod, Object[] args) throwsThrowable {
MethodInvocationinvocation;
ObjectoldProxy = null;
booleansetProxyContext = false;
TargetSourcetargetSource = this.advised.targetSource;
Class<?> targetClass = null;
Objecttarget = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.returnequals(args[0]);
}
elseif (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.returnhashCode();
}
elseif (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.returnAopProxyUtils.ultimateTargetClass(this.advised);
}
elseif (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...returnAopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
ObjectretVal;
if (this.advised.exposeProxy) {
// Make invocation available if necessary.oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// May be null. Get as late as possible to minimize the time we "own" the target,// in case it comes from a pool.target = targetSource.getTarget();
if (target != null) {
targetClass = target.getClass();
}
// Get the interception chain for this method.List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct// reflective invocation of the target, and avoid creating a MethodInvocation.if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly// Note that the final invoker must be an InvokerInterceptor so we know it does// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...invocation = newReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.retVal = invocation.proceed();
}
// Massage return value if necessary.Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method// is type-compatible. Note that we can't help if the target sets// a reference to itself in another returned object.retVal = proxy;
}
elseif (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
thrownewAopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
returnretVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.AopContext.setCurrentProxy(oldProxy);
}
}
}
/** * Equality means interfaces, advisors and TargetSource are equal. * <p>The compared object may be a JdkDynamicAopProxy instance itself * or a dynamic proxy wrapping a JdkDynamicAopProxy instance. */@Overridepublicbooleanequals(Objectother) {
if (other == this) {
returntrue;
}
if (other == null) {
returnfalse;
}
JdkDynamicAopProxyotherProxy;
if (otherinstanceofJdkDynamicAopProxy) {
otherProxy = (JdkDynamicAopProxy) other;
}
elseif (Proxy.isProxyClass(other.getClass())) {
InvocationHandlerih = Proxy.getInvocationHandler(other);
if (!(ihinstanceofJdkDynamicAopProxy)) {
returnfalse;
}
otherProxy = (JdkDynamicAopProxy) ih;
}
else {
// Not a valid comparison...returnfalse;
}
// If we get here, otherProxy is the other AopProxy.returnAopProxyUtils.equalsInProxy(this.advised, otherProxy.advised);
}
/** * Proxy uses the hash code of the TargetSource. */@OverridepublicinthashCode() {
returnJdkDynamicAopProxy.class.hashCode() * 13 + this.advised.getTargetSource().hashCode();
}
}
CglibAopProxy.java
packageorg.springframework.aop.framework;
@SuppressWarnings("serial")
classCglibAopProxyimplementsAopProxy, Serializable {
// Constants for CGLIB callback array indicesprivatestaticfinalintAOP_PROXY = 0;
privatestaticfinalintINVOKE_TARGET = 1;
privatestaticfinalintNO_OVERRIDE = 2;
privatestaticfinalintDISPATCH_TARGET = 3;
privatestaticfinalintDISPATCH_ADVISED = 4;
privatestaticfinalintINVOKE_EQUALS = 5;
privatestaticfinalintINVOKE_HASHCODE = 6;
protectedstaticfinalLoglogger = LogFactory.getLog(CglibAopProxy.class);
privatestaticfinalMap<Class<?>, Boolean> validatedClasses = newWeakHashMap<Class<?>, Boolean>();
protectedfinalAdvisedSupportadvised;
protectedObject[] constructorArgs;
protectedClass<?>[] constructorArgTypes;
privatefinaltransientAdvisedDispatcheradvisedDispatcher;
privatetransientMap<String, Integer> fixedInterceptorMap;
privatetransientintfixedInterceptorOffset;
publicCglibAopProxy(AdvisedSupportconfig) throwsAopConfigException {
Assert.notNull(config, "AdvisedSupport must not be null");
if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
thrownewAopConfigException("No advisors and no TargetSource specified");
}
this.advised = config;
this.advisedDispatcher = newAdvisedDispatcher(this.advised);
}
publicvoidsetConstructorArguments(Object[] constructorArgs, Class<?>[] constructorArgTypes) {
if (constructorArgs == null || constructorArgTypes == null) {
thrownewIllegalArgumentException("Both 'constructorArgs' and 'constructorArgTypes' need to be specified");
}
if (constructorArgs.length != constructorArgTypes.length) {
thrownewIllegalArgumentException("Number of 'constructorArgs' (" + constructorArgs.length +
") must match number of 'constructorArgTypes' (" + constructorArgTypes.length + ")");
}
this.constructorArgs = constructorArgs;
this.constructorArgTypes = constructorArgTypes;
}
@OverridepublicObjectgetProxy() {
returngetProxy(null);
}
@OverridepublicObjectgetProxy(ClassLoaderclassLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
}
try {
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
if (ClassUtils.isCglibProxyClass(rootClass)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// Validate the class, writing log messages as necessary.validateClassIfNecessary(proxySuperClass, classLoader);
// Configure CGLIB Enhancer...Enhancerenhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoaderinstanceofSmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(newClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = newClass<?>[callbacks.length];
for (intx = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call aboveenhancer.setCallbackFilter(newProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.returncreateProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationExceptionex) {
thrownewAopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (IllegalArgumentExceptionex) {
thrownewAopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwableex) {
// TargetSource.getTarget() failedthrownewAopConfigException("Unexpected AOP exception", ex);
}
}
protectedObjectcreateProxyClassAndInstance(Enhancerenhancer, Callback[] callbacks) {
enhancer.setInterceptDuringConstruction(false);
enhancer.setCallbacks(callbacks);
return (this.constructorArgs != null ?
enhancer.create(this.constructorArgTypes, this.constructorArgs) :
enhancer.create());
}
protectedEnhancercreateEnhancer() {
returnnewEnhancer();
}
privatevoidvalidateClassIfNecessary(Class<?> proxySuperClass, ClassLoaderproxyClassLoader) {
if (logger.isWarnEnabled()) {
synchronized (validatedClasses) {
if (!validatedClasses.containsKey(proxySuperClass)) {
doValidateClass(proxySuperClass, proxyClassLoader,
ClassUtils.getAllInterfacesForClassAsSet(proxySuperClass));
validatedClasses.put(proxySuperClass, Boolean.TRUE);
}
}
}
}
privatevoiddoValidateClass(Class<?> proxySuperClass, ClassLoaderproxyClassLoader, Set<Class<?>> ifcs) {
if (proxySuperClass != Object.class) {
Method[] methods = proxySuperClass.getDeclaredMethods();
for (Methodmethod : methods) {
intmod = method.getModifiers();
if (!Modifier.isStatic(mod) && !Modifier.isPrivate(mod)) {
if (Modifier.isFinal(mod)) {
if (implementsInterface(method, ifcs)) {
logger.warn("Unable to proxy interface-implementing method [" + method + "] because " +
"it is marked as final: Consider using interface-based JDK proxies instead!");
}
logger.info("Final method [" + method + "] cannot get proxied via CGLIB: " +
"Calls to this method will NOT be routed to the target instance and " +
"might lead to NPEs against uninitialized fields in the proxy instance.");
}
elseif (!Modifier.isPublic(mod) && !Modifier.isProtected(mod) &&
proxyClassLoader != null && proxySuperClass.getClassLoader() != proxyClassLoader) {
logger.info("Method [" + method + "] is package-visible across different ClassLoaders " +
"and cannot get proxied via CGLIB: Declare this method as public or protected " +
"if you need to support invocations through the proxy.");
}
}
}
doValidateClass(proxySuperClass.getSuperclass(), proxyClassLoader, ifcs);
}
}
privateCallback[] getCallbacks(Class<?> rootClass) throwsException {
// Parameters used for optimization choices...booleanexposeProxy = this.advised.isExposeProxy();
booleanisFrozen = this.advised.isFrozen();
booleanisStatic = this.advised.getTargetSource().isStatic();
// Choose an "aop" interceptor (used for AOP calls).CallbackaopInterceptor = newDynamicAdvisedInterceptor(this.advised);
// Choose a "straight to target" interceptor. (used for calls that are// unadvised but can return this). May be required to expose the proxy.CallbacktargetInterceptor;
if (exposeProxy) {
targetInterceptor = (isStatic ?
newStaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
newDynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
}
else {
targetInterceptor = (isStatic ?
newStaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
newDynamicUnadvisedInterceptor(this.advised.getTargetSource()));
}
// Choose a "direct to target" dispatcher (used for// unadvised calls to static targets that cannot return this).CallbacktargetDispatcher = (isStatic ?
newStaticDispatcher(this.advised.getTargetSource().getTarget()) : newSerializableNoOp());
Callback[] mainCallbacks = newCallback[] {
aopInterceptor, // for normal advicetargetInterceptor, // invoke target without considering advice, if optimizednewSerializableNoOp(), // no override for methods mapped to thistargetDispatcher, this.advisedDispatcher,
newEqualsInterceptor(this.advised),
newHashCodeInterceptor(this.advised)
};
Callback[] callbacks;
// If the target is a static one and the advice chain is frozen,// then we can make some optimizations by sending the AOP calls// direct to the target using the fixed chain for that method.if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = newCallback[methods.length];
this.fixedInterceptorMap = newHashMap<String, Integer>(methods.length);
// TODO: small memory optimization here (can skip creation for methods with no advice)for (intx = 0; x < methods.length; x++) {
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
fixedCallbacks[x] = newFixedChainStaticTargetInterceptor(
chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
this.fixedInterceptorMap.put(methods[x].toString(), x);
}
// Now copy both the callbacks from mainCallbacks// and fixedCallbacks into the callbacks array.callbacks = newCallback[mainCallbacks.length + fixedCallbacks.length];
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
this.fixedInterceptorOffset = mainCallbacks.length;
}
else {
callbacks = mainCallbacks;
}
returncallbacks;
}
@Overridepublicbooleanequals(Objectother) {
return (this == other || (otherinstanceofCglibAopProxy &&
AopProxyUtils.equalsInProxy(this.advised, ((CglibAopProxy) other).advised)));
}
@OverridepublicinthashCode() {
returnCglibAopProxy.class.hashCode() * 13 + this.advised.getTargetSource().hashCode();
}
privatestaticbooleanimplementsInterface(Methodmethod, Set<Class<?>> ifcs) {
for (Class<?> ifc : ifcs) {
if (ClassUtils.hasMethod(ifc, method.getName(), method.getParameterTypes())) {
returntrue;
}
}
returnfalse;
}
privatestaticObjectprocessReturnType(Objectproxy, Objecttarget, Methodmethod, ObjectretVal) {
// Massage return value if necessaryif (retVal != null && retVal == target &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// 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;
}
Class<?> returnType = method.getReturnType();
if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
thrownewAopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
returnretVal;
}
publicstaticclassSerializableNoOpimplementsNoOp, Serializable {
}
privatestaticclassStaticUnadvisedInterceptorimplementsMethodInterceptor, Serializable {
privatefinalObjecttarget;
publicStaticUnadvisedInterceptor(Objecttarget) {
this.target = target;
}
@OverridepublicObjectintercept(Objectproxy, Methodmethod, Object[] args, MethodProxymethodProxy) throwsThrowable {
ObjectretVal = methodProxy.invoke(this.target, args);
returnprocessReturnType(proxy, this.target, method, retVal);
}
}
privatestaticclassStaticUnadvisedExposedInterceptorimplementsMethodInterceptor, Serializable {
privatefinalObjecttarget;
publicStaticUnadvisedExposedInterceptor(Objecttarget) {
this.target = target;
}
@OverridepublicObjectintercept(Objectproxy, Methodmethod, Object[] args, MethodProxymethodProxy) throwsThrowable {
ObjectoldProxy = null;
try {
oldProxy = AopContext.setCurrentProxy(proxy);
ObjectretVal = methodProxy.invoke(this.target, args);
returnprocessReturnType(proxy, this.target, method, retVal);
}
finally {
AopContext.setCurrentProxy(oldProxy);
}
}
}
privatestaticclassDynamicUnadvisedInterceptorimplementsMethodInterceptor, Serializable {
privatefinalTargetSourcetargetSource;
publicDynamicUnadvisedInterceptor(TargetSourcetargetSource) {
this.targetSource = targetSource;
}
@OverridepublicObjectintercept(Objectproxy, Methodmethod, Object[] args, MethodProxymethodProxy) throwsThrowable {
Objecttarget = this.targetSource.getTarget();
try {
ObjectretVal = methodProxy.invoke(target, args);
returnprocessReturnType(proxy, target, method, retVal);
}
finally {
this.targetSource.releaseTarget(target);
}
}
}
privatestaticclassDynamicUnadvisedExposedInterceptorimplementsMethodInterceptor, Serializable {
privatefinalTargetSourcetargetSource;
publicDynamicUnadvisedExposedInterceptor(TargetSourcetargetSource) {
this.targetSource = targetSource;
}
@OverridepublicObjectintercept(Objectproxy, Methodmethod, Object[] args, MethodProxymethodProxy) throwsThrowable {
ObjectoldProxy = null;
Objecttarget = this.targetSource.getTarget();
try {
oldProxy = AopContext.setCurrentProxy(proxy);
ObjectretVal = methodProxy.invoke(target, args);
returnprocessReturnType(proxy, target, method, retVal);
}
finally {
AopContext.setCurrentProxy(oldProxy);
this.targetSource.releaseTarget(target);
}
}
}
privatestaticclassStaticDispatcherimplementsDispatcher, Serializable {
privateObjecttarget;
publicStaticDispatcher(Objecttarget) {
this.target = target;
}
@OverridepublicObjectloadObject() {
returnthis.target;
}
}
privatestaticclassAdvisedDispatcherimplementsDispatcher, Serializable {
privatefinalAdvisedSupportadvised;
publicAdvisedDispatcher(AdvisedSupportadvised) {
this.advised = advised;
}
@OverridepublicObjectloadObject() throwsException {
returnthis.advised;
}
}
privatestaticclassEqualsInterceptorimplementsMethodInterceptor, Serializable {
privatefinalAdvisedSupportadvised;
publicEqualsInterceptor(AdvisedSupportadvised) {
this.advised = advised;
}
@OverridepublicObjectintercept(Objectproxy, Methodmethod, Object[] args, MethodProxymethodProxy) {
Objectother = args[0];
if (proxy == other) {
returntrue;
}
if (otherinstanceofFactory) {
Callbackcallback = ((Factory) other).getCallback(INVOKE_EQUALS);
if (!(callbackinstanceofEqualsInterceptor)) {
returnfalse;
}
AdvisedSupportotherAdvised = ((EqualsInterceptor) callback).advised;
returnAopProxyUtils.equalsInProxy(this.advised, otherAdvised);
}
else {
returnfalse;
}
}
}
privatestaticclassHashCodeInterceptorimplementsMethodInterceptor, Serializable {
privatefinalAdvisedSupportadvised;
publicHashCodeInterceptor(AdvisedSupportadvised) {
this.advised = advised;
}
@OverridepublicObjectintercept(Objectproxy, Methodmethod, Object[] args, MethodProxymethodProxy) {
returnCglibAopProxy.class.hashCode() * 13 + this.advised.getTargetSource().hashCode();
}
}
privatestaticclassFixedChainStaticTargetInterceptorimplementsMethodInterceptor, Serializable {
privatefinalList<Object> adviceChain;
privatefinalObjecttarget;
privatefinalClass<?> targetClass;
publicFixedChainStaticTargetInterceptor(List<Object> adviceChain, Objecttarget, Class<?> targetClass) {
this.adviceChain = adviceChain;
this.target = target;
this.targetClass = targetClass;
}
@OverridepublicObjectintercept(Objectproxy, Methodmethod, Object[] args, MethodProxymethodProxy) throwsThrowable {
MethodInvocationinvocation = newCglibMethodInvocation(proxy, this.target, method, args,
this.targetClass, this.adviceChain, methodProxy);
// If we get here, we need to create a MethodInvocation.ObjectretVal = invocation.proceed();
retVal = processReturnType(proxy, this.target, method, retVal);
returnretVal;
}
}
privatestaticclassDynamicAdvisedInterceptorimplementsMethodInterceptor, Serializable {
privatefinalAdvisedSupportadvised;
publicDynamicAdvisedInterceptor(AdvisedSupportadvised) {
this.advised = advised;
}
@OverridepublicObjectintercept(Objectproxy, Methodmethod, Object[] args, MethodProxymethodProxy) throwsThrowable {
ObjectoldProxy = null;
booleansetProxyContext = false;
Class<?> targetClass = null;
Objecttarget = null;
try {
if (this.advised.exposeProxy) {
// Make invocation available if necessary.oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// May be null. 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<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
ObjectretVal;
// Check whether we only have one InvokerInterceptor: that is,// no real advice, but just reflective invocation of the target.if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// We can skip creating a MethodInvocation: just invoke the target directly.// Note that the final invoker must be an InvokerInterceptor, so we know// it does nothing but a reflective operation on the target, and no hot// swapping or fancy proxying.Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// We need to create a method invocation...retVal = newCglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
returnretVal;
}
finally {
if (target != null) {
releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.AopContext.setCurrentProxy(oldProxy);
}
}
}
@Overridepublicbooleanequals(Objectother) {
return (this == other ||
(otherinstanceofDynamicAdvisedInterceptor &&
this.advised.equals(((DynamicAdvisedInterceptor) other).advised)));
}
/** * CGLIB uses this to drive proxy creation. */@OverridepublicinthashCode() {
returnthis.advised.hashCode();
}
protectedObjectgetTarget() throwsException {
returnthis.advised.getTargetSource().getTarget();
}
protectedvoidreleaseTarget(Objecttarget) throwsException {
this.advised.getTargetSource().releaseTarget(target);
}
}
privatestaticclassCglibMethodInvocationextendsReflectiveMethodInvocation {
privatefinalMethodProxymethodProxy;
privatefinalbooleanpublicMethod;
publicCglibMethodInvocation(Objectproxy, Objecttarget, Methodmethod, Object[] arguments,
Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers, MethodProxymethodProxy) {
super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);
this.methodProxy = methodProxy;
this.publicMethod = Modifier.isPublic(method.getModifiers());
}
/** * Gives a marginal performance improvement versus using reflection to * invoke the target when invoking public methods. */@OverrideprotectedObjectinvokeJoinpoint() throwsThrowable {
if (this.publicMethod) {
returnthis.methodProxy.invoke(this.target, this.arguments);
}
else {
returnsuper.invokeJoinpoint();
}
}
}
privatestaticclassProxyCallbackFilterimplementsCallbackFilter {
privatefinalAdvisedSupportadvised;
privatefinalMap<String, Integer> fixedInterceptorMap;
privatefinalintfixedInterceptorOffset;
publicProxyCallbackFilter(AdvisedSupportadvised, Map<String, Integer> fixedInterceptorMap, intfixedInterceptorOffset) {
this.advised = advised;
this.fixedInterceptorMap = fixedInterceptorMap;
this.fixedInterceptorOffset = fixedInterceptorOffset;
}
@Overridepublicintaccept(Methodmethod) {
if (AopUtils.isFinalizeMethod(method)) {
logger.debug("Found finalize() method - using NO_OVERRIDE");
returnNO_OVERRIDE;
}
if (!this.advised.isOpaque() && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
if (logger.isDebugEnabled()) {
logger.debug("Method is declared on Advised interface: " + method);
}
returnDISPATCH_ADVISED;
}
// We must always proxy equals, to direct calls to this.if (AopUtils.isEqualsMethod(method)) {
if (logger.isDebugEnabled()) {
logger.debug("Found 'equals' method: " + method);
}
returnINVOKE_EQUALS;
}
// We must always calculate hashCode based on the proxy.if (AopUtils.isHashCodeMethod(method)) {
if (logger.isDebugEnabled()) {
logger.debug("Found 'hashCode' method: " + method);
}
returnINVOKE_HASHCODE;
}
Class<?> targetClass = this.advised.getTargetClass();
// Proxy is not yet available, but that shouldn't matter.List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
booleanhaveAdvice = !chain.isEmpty();
booleanexposeProxy = this.advised.isExposeProxy();
booleanisStatic = this.advised.getTargetSource().isStatic();
booleanisFrozen = this.advised.isFrozen();
if (haveAdvice || !isFrozen) {
// If exposing the proxy, then AOP_PROXY must be used.if (exposeProxy) {
if (logger.isDebugEnabled()) {
logger.debug("Must expose proxy on advised method: " + method);
}
returnAOP_PROXY;
}
Stringkey = method.toString();
// Check to see if we have fixed interceptor to serve this method.// Else use the AOP_PROXY.if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(key)) {
if (logger.isDebugEnabled()) {
logger.debug("Method has advice and optimizations are enabled: " + method);
}
// We know that we are optimizing so we can use the FixedStaticChainInterceptors.intindex = this.fixedInterceptorMap.get(key);
return (index + this.fixedInterceptorOffset);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Unable to apply any optimizations to advised method: " + method);
}
returnAOP_PROXY;
}
}
else {
// See if the return type of the method is outside the class hierarchy of the target type.// If so we know it never needs to have return type massage and can use a dispatcher.// If the proxy is being exposed, then must use the interceptor the correct one is already// configured. If the target is not static, then we cannot use a dispatcher because the// target needs to be explicitly released after the invocation.if (exposeProxy || !isStatic) {
returnINVOKE_TARGET;
}
Class<?> returnType = method.getReturnType();
if (returnType.isAssignableFrom(targetClass)) {
if (logger.isDebugEnabled()) {
logger.debug("Method return type is assignable from target type and " +
"may therefore return 'this' - using INVOKE_TARGET: " + method);
}
returnINVOKE_TARGET;
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Method return type ensures 'this' cannot be returned - " +
"using DISPATCH_TARGET: " + method);
}
returnDISPATCH_TARGET;
}
}
}
@Overridepublicbooleanequals(Objectother) {
if (this == other) {
returntrue;
}
if (!(otherinstanceofProxyCallbackFilter)) {
returnfalse;
}
ProxyCallbackFilterotherCallbackFilter = (ProxyCallbackFilter) other;
AdvisedSupportotherAdvised = otherCallbackFilter.advised;
if (this.advised == null || otherAdvised == null) {
returnfalse;
}
if (this.advised.isFrozen() != otherAdvised.isFrozen()) {
returnfalse;
}
if (this.advised.isExposeProxy() != otherAdvised.isExposeProxy()) {
returnfalse;
}
if (this.advised.getTargetSource().isStatic() != otherAdvised.getTargetSource().isStatic()) {
returnfalse;
}
if (!AopProxyUtils.equalsProxiedInterfaces(this.advised, otherAdvised)) {
returnfalse;
}
// Advice instance identity is unimportant to the proxy class:// All that matters is type and ordering.Advisor[] thisAdvisors = this.advised.getAdvisors();
Advisor[] thatAdvisors = otherAdvised.getAdvisors();
if (thisAdvisors.length != thatAdvisors.length) {
returnfalse;
}
for (inti = 0; i < thisAdvisors.length; i++) {
AdvisorthisAdvisor = thisAdvisors[i];
AdvisorthatAdvisor = thatAdvisors[i];
if (!equalsAdviceClasses(thisAdvisor, thatAdvisor)) {
returnfalse;
}
if (!equalsPointcuts(thisAdvisor, thatAdvisor)) {
returnfalse;
}
}
returntrue;
}
privatebooleanequalsAdviceClasses(Advisora, Advisorb) {
Adviceaa = a.getAdvice();
Adviceba = b.getAdvice();
if (aa == null || ba == null) {
return (aa == ba);
}
return (aa.getClass() == ba.getClass());
}
privatebooleanequalsPointcuts(Advisora, Advisorb) {
// If only one of the advisor (but not both) is PointcutAdvisor, then it is a mismatch.// Takes care of the situations where an IntroductionAdvisor is used (see SPR-3959).return (!(ainstanceofPointcutAdvisor) ||
(binstanceofPointcutAdvisor &&
ObjectUtils.nullSafeEquals(((PointcutAdvisor) a).getPointcut(), ((PointcutAdvisor) b).getPointcut())));
}
@OverridepublicinthashCode() {
inthashCode = 0;
Advisor[] advisors = this.advised.getAdvisors();
for (Advisoradvisor : advisors) {
Adviceadvice = advisor.getAdvice();
if (advice != null) {
hashCode = 13 * hashCode + advice.getClass().hashCode();
}
}
hashCode = 13 * hashCode + (this.advised.isFrozen() ? 1 : 0);
hashCode = 13 * hashCode + (this.advised.isExposeProxy() ? 1 : 0);
hashCode = 13 * hashCode + (this.advised.isOptimize() ? 1 : 0);
hashCode = 13 * hashCode + (this.advised.isOpaque() ? 1 : 0);
returnhashCode;
}
}
privatestaticclassClassLoaderAwareUndeclaredThrowableStrategyextendsUndeclaredThrowableStrategy {
privatefinalClassLoaderclassLoader;
publicClassLoaderAwareUndeclaredThrowableStrategy(ClassLoaderclassLoader) {
super(UndeclaredThrowableException.class);
this.classLoader = classLoader;
}
@Overridepublicbyte[] generate(ClassGeneratorcg) throwsException {
if (this.classLoader == null) {
returnsuper.generate(cg);
}
ThreadcurrentThread = Thread.currentThread();
ClassLoaderthreadContextClassLoader;
try {
threadContextClassLoader = currentThread.getContextClassLoader();
}
catch (Throwableex) {
// Cannot access thread context ClassLoader - falling back...returnsuper.generate(cg);
}
booleanoverrideClassLoader = !this.classLoader.equals(threadContextClassLoader);
if (overrideClassLoader) {
currentThread.setContextClassLoader(this.classLoader);
}
try {
returnsuper.generate(cg);
}
finally {
if (overrideClassLoader) {
// Reset original thread context ClassLoader.currentThread.setContextClassLoader(threadContextClassLoader);
}
}
}
}
}
ObjenesisCglibAopProxy.java
packageorg.springframework.aop.framework;
@SuppressWarnings("serial")
classObjenesisCglibAopProxyextendsCglibAopProxy {
privatestaticfinalLoglogger = LogFactory.getLog(ObjenesisCglibAopProxy.class);
privatestaticfinalSpringObjenesisobjenesis = newSpringObjenesis();
publicObjenesisCglibAopProxy(AdvisedSupportconfig) {
super(config);
}
@Override@SuppressWarnings("unchecked")
protectedObjectcreateProxyClassAndInstance(Enhancerenhancer, Callback[] callbacks) {
Class<?> proxyClass = enhancer.createClass();
ObjectproxyInstance = null;
if (objenesis.isWorthTrying()) {
try {
proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
}
catch (Throwableex) {
logger.debug("Unable to instantiate proxy using Objenesis, " +
"falling back to regular proxy construction", ex);
}
}
if (proxyInstance == null) {
// Regular instantiation via default constructor...try {
proxyInstance = (this.constructorArgs != null ?
proxyClass.getConstructor(this.constructorArgTypes).newInstance(this.constructorArgs) :
proxyClass.newInstance());
}
catch (Throwableex) {
thrownewAopConfigException("Unable to instantiate proxy using Objenesis, " +
"and regular proxy instantiation via default constructor fails as well", ex);
}
}
((Factory) proxyInstance).setCallbacks(callbacks);
returnproxyInstance;
}
}
packageorg.springframework.aop.framework;
publicclassAdvisedSupportextendsProxyConfigimplementsAdvised {
privatestaticfinallongserialVersionUID = 2651364800145442165L;
publicstaticfinalTargetSourceEMPTY_TARGET_SOURCE = EmptyTargetSource.INSTANCE;
TargetSourcetargetSource = EMPTY_TARGET_SOURCE;
privatebooleanpreFiltered = false;
AdvisorChainFactoryadvisorChainFactory = newDefaultAdvisorChainFactory();
privatetransientMap<MethodCacheKey, List<Object>> methodCache;
privateList<Class<?>> interfaces = newArrayList<Class<?>>();
privateList<Advisor> advisors = newArrayList<Advisor>();
privateAdvisor[] advisorArray = newAdvisor[0];
publicAdvisedSupport() {
initMethodCache();
}
publicAdvisedSupport(Class<?>... interfaces) {
this();
setInterfaces(interfaces);
}
privatevoidinitMethodCache() {
this.methodCache = newConcurrentHashMap<MethodCacheKey, List<Object>>(32);
}
publicvoidsetTarget(Objecttarget) {
setTargetSource(newSingletonTargetSource(target));
}
@OverridepublicvoidsetTargetSource(TargetSourcetargetSource) {
this.targetSource = (targetSource != null ? targetSource : EMPTY_TARGET_SOURCE);
}
@OverridepublicTargetSourcegetTargetSource() {
returnthis.targetSource;
}
publicvoidsetTargetClass(Class<?> targetClass) {
this.targetSource = EmptyTargetSource.forClass(targetClass);
}
@OverridepublicClass<?> getTargetClass() {
returnthis.targetSource.getTargetClass();
}
@OverridepublicvoidsetPreFiltered(booleanpreFiltered) {
this.preFiltered = preFiltered;
}
@OverridepublicbooleanisPreFiltered() {
returnthis.preFiltered;
}
publicvoidsetAdvisorChainFactory(AdvisorChainFactoryadvisorChainFactory) {
Assert.notNull(advisorChainFactory, "AdvisorChainFactory must not be null");
this.advisorChainFactory = advisorChainFactory;
}
publicAdvisorChainFactorygetAdvisorChainFactory() {
returnthis.advisorChainFactory;
}
publicvoidsetInterfaces(Class<?>... interfaces) {
Assert.notNull(interfaces, "Interfaces must not be null");
this.interfaces.clear();
for (Class<?> ifc : interfaces) {
addInterface(ifc);
}
}
publicvoidaddInterface(Class<?> intf) {
Assert.notNull(intf, "Interface must not be null");
if (!intf.isInterface()) {
thrownewIllegalArgumentException("[" + intf.getName() + "] is not an interface");
}
if (!this.interfaces.contains(intf)) {
this.interfaces.add(intf);
adviceChanged();
}
}
publicbooleanremoveInterface(Class<?> intf) {
returnthis.interfaces.remove(intf);
}
@OverridepublicClass<?>[] getProxiedInterfaces() {
returnClassUtils.toClassArray(this.interfaces);
}
@OverridepublicbooleanisInterfaceProxied(Class<?> intf) {
for (Class<?> proxyIntf : this.interfaces) {
if (intf.isAssignableFrom(proxyIntf)) {
returntrue;
}
}
returnfalse;
}
@OverridepublicfinalAdvisor[] getAdvisors() {
returnthis.advisorArray;
}
@OverridepublicvoidaddAdvisor(Advisoradvisor) {
intpos = this.advisors.size();
addAdvisor(pos, advisor);
}
@OverridepublicvoidaddAdvisor(intpos, Advisoradvisor) throwsAopConfigException {
if (advisorinstanceofIntroductionAdvisor) {
validateIntroductionAdvisor((IntroductionAdvisor) advisor);
}
addAdvisorInternal(pos, advisor);
}
@OverridepublicbooleanremoveAdvisor(Advisoradvisor) {
intindex = indexOf(advisor);
if (index == -1) {
returnfalse;
}
else {
removeAdvisor(index);
returntrue;
}
}
@OverridepublicvoidremoveAdvisor(intindex) throwsAopConfigException {
if (isFrozen()) {
thrownewAopConfigException("Cannot remove Advisor: Configuration is frozen.");
}
if (index < 0 || index > this.advisors.size() - 1) {
thrownewAopConfigException("Advisor index " + index + " is out of bounds: " +
"This configuration only has " + this.advisors.size() + " advisors.");
}
Advisoradvisor = this.advisors.get(index);
if (advisorinstanceofIntroductionAdvisor) {
IntroductionAdvisoria = (IntroductionAdvisor) advisor;
// We need to remove introduction interfaces.for (intj = 0; j < ia.getInterfaces().length; j++) {
removeInterface(ia.getInterfaces()[j]);
}
}
this.advisors.remove(index);
updateAdvisorArray();
adviceChanged();
}
@OverridepublicintindexOf(Advisoradvisor) {
Assert.notNull(advisor, "Advisor must not be null");
returnthis.advisors.indexOf(advisor);
}
@OverridepublicbooleanreplaceAdvisor(Advisora, Advisorb) throwsAopConfigException {
Assert.notNull(a, "Advisor a must not be null");
Assert.notNull(b, "Advisor b must not be null");
intindex = indexOf(a);
if (index == -1) {
returnfalse;
}
removeAdvisor(index);
addAdvisor(index, b);
returntrue;
}
publicvoidaddAdvisors(Advisor... advisors) {
addAdvisors(Arrays.asList(advisors));
}
publicvoidaddAdvisors(Collection<Advisor> advisors) {
if (isFrozen()) {
thrownewAopConfigException("Cannot add advisor: Configuration is frozen.");
}
if (!CollectionUtils.isEmpty(advisors)) {
for (Advisoradvisor : advisors) {
if (advisorinstanceofIntroductionAdvisor) {
validateIntroductionAdvisor((IntroductionAdvisor) advisor);
}
Assert.notNull(advisor, "Advisor must not be null");
this.advisors.add(advisor);
}
updateAdvisorArray();
adviceChanged();
}
}
privatevoidvalidateIntroductionAdvisor(IntroductionAdvisoradvisor) {
advisor.validateInterfaces();
// If the advisor passed validation, we can make the change.Class<?>[] ifcs = advisor.getInterfaces();
for (Class<?> ifc : ifcs) {
addInterface(ifc);
}
}
privatevoidaddAdvisorInternal(intpos, Advisoradvisor) throwsAopConfigException {
Assert.notNull(advisor, "Advisor must not be null");
if (isFrozen()) {
thrownewAopConfigException("Cannot add advisor: Configuration is frozen.");
}
if (pos > this.advisors.size()) {
thrownewIllegalArgumentException(
"Illegal position " + pos + " in advisor list with size " + this.advisors.size());
}
this.advisors.add(pos, advisor);
updateAdvisorArray();
adviceChanged();
}
protectedfinalvoidupdateAdvisorArray() {
this.advisorArray = this.advisors.toArray(newAdvisor[this.advisors.size()]);
}
protectedfinalList<Advisor> getAdvisorsInternal() {
returnthis.advisors;
}
@OverridepublicvoidaddAdvice(Adviceadvice) throwsAopConfigException {
intpos = this.advisors.size();
addAdvice(pos, advice);
}
@OverridepublicvoidaddAdvice(intpos, Adviceadvice) throwsAopConfigException {
Assert.notNull(advice, "Advice must not be null");
if (adviceinstanceofIntroductionInfo) {
// We don't need an IntroductionAdvisor for this kind of introduction:// It's fully self-describing.addAdvisor(pos, newDefaultIntroductionAdvisor(advice, (IntroductionInfo) advice));
}
elseif (adviceinstanceofDynamicIntroductionAdvice) {
// We need an IntroductionAdvisor for this kind of introduction.thrownewAopConfigException("DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor");
}
else {
addAdvisor(pos, newDefaultPointcutAdvisor(advice));
}
}
@OverridepublicbooleanremoveAdvice(Adviceadvice) throwsAopConfigException {
intindex = indexOf(advice);
if (index == -1) {
returnfalse;
}
else {
removeAdvisor(index);
returntrue;
}
}
@OverridepublicintindexOf(Adviceadvice) {
Assert.notNull(advice, "Advice must not be null");
for (inti = 0; i < this.advisors.size(); i++) {
Advisoradvisor = this.advisors.get(i);
if (advisor.getAdvice() == advice) {
returni;
}
}
return -1;
}
publicbooleanadviceIncluded(Adviceadvice) {
if (advice != null) {
for (Advisoradvisor : this.advisors) {
if (advisor.getAdvice() == advice) {
returntrue;
}
}
}
returnfalse;
}
publicintcountAdvicesOfType(Class<?> adviceClass) {
intcount = 0;
if (adviceClass != null) {
for (Advisoradvisor : this.advisors) {
if (adviceClass.isInstance(advisor.getAdvice())) {
count++;
}
}
}
returncount;
}
publicList<Object> getInterceptorsAndDynamicInterceptionAdvice(Methodmethod, Class<?> targetClass) {
MethodCacheKeycacheKey = newMethodCacheKey(method);
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
returncached;
}
protectedvoidadviceChanged() {
this.methodCache.clear();
}
protectedvoidcopyConfigurationFrom(AdvisedSupportother) {
copyConfigurationFrom(other, other.targetSource, newArrayList<Advisor>(other.advisors));
}
protectedvoidcopyConfigurationFrom(AdvisedSupportother, TargetSourcetargetSource, List<Advisor> advisors) {
copyFrom(other);
this.targetSource = targetSource;
this.advisorChainFactory = other.advisorChainFactory;
this.interfaces = newArrayList<Class<?>>(other.interfaces);
for (Advisoradvisor : advisors) {
if (advisorinstanceofIntroductionAdvisor) {
validateIntroductionAdvisor((IntroductionAdvisor) advisor);
}
Assert.notNull(advisor, "Advisor must not be null");
this.advisors.add(advisor);
}
updateAdvisorArray();
adviceChanged();
}
AdvisedSupportgetConfigurationOnlyCopy() {
AdvisedSupportcopy = newAdvisedSupport();
copy.copyFrom(this);
copy.targetSource = EmptyTargetSource.forClass(getTargetClass(), getTargetSource().isStatic());
copy.advisorChainFactory = this.advisorChainFactory;
copy.interfaces = this.interfaces;
copy.advisors = this.advisors;
copy.updateAdvisorArray();
returncopy;
}
//---------------------------------------------------------------------// Serialization support//---------------------------------------------------------------------privatevoidreadObject(ObjectInputStreamois) throwsIOException, ClassNotFoundException {
// Rely on default serialization; just initialize state after deserialization.ois.defaultReadObject();
// Initialize transient fields.initMethodCache();
}
@OverridepublicStringtoProxyConfigString() {
returntoString();
}
@OverridepublicStringtoString() {
StringBuildersb = newStringBuilder(getClass().getName());
sb.append(": ").append(this.interfaces.size()).append(" interfaces ");
sb.append(ClassUtils.classNamesToString(this.interfaces)).append("; ");
sb.append(this.advisors.size()).append(" advisors ");
sb.append(this.advisors).append("; ");
sb.append("targetSource [").append(this.targetSource).append("]; ");
sb.append(super.toString());
returnsb.toString();
}
privatestaticfinalclassMethodCacheKeyimplementsComparable<MethodCacheKey> {
privatefinalMethodmethod;
privatefinalinthashCode;
publicMethodCacheKey(Methodmethod) {
this.method = method;
this.hashCode = method.hashCode();
}
@Overridepublicbooleanequals(Objectother) {
return (this == other || (otherinstanceofMethodCacheKey &&
this.method == ((MethodCacheKey) other).method));
}
@OverridepublicinthashCode() {
returnthis.hashCode;
}
@OverridepublicStringtoString() {
returnthis.method.toString();
}
@OverridepublicintcompareTo(MethodCacheKeyother) {
intresult = this.method.getName().compareTo(other.method.getName());
if (result == 0) {
result = this.method.toString().compareTo(other.method.toString());
}
returnresult;
}
}
}
ProxyCreatorSupport.java
packageorg.springframework.aop.framework;
@SuppressWarnings("serial")
publicclassProxyCreatorSupportextendsAdvisedSupport {
privateAopProxyFactoryaopProxyFactory;
privatefinalList<AdvisedSupportListener> listeners = newLinkedList<AdvisedSupportListener>();
privatebooleanactive = false;
publicProxyCreatorSupport() {
this.aopProxyFactory = newDefaultAopProxyFactory();
}
publicProxyCreatorSupport(AopProxyFactoryaopProxyFactory) {
Assert.notNull(aopProxyFactory, "AopProxyFactory must not be null");
this.aopProxyFactory = aopProxyFactory;
}
publicvoidsetAopProxyFactory(AopProxyFactoryaopProxyFactory) {
Assert.notNull(aopProxyFactory, "AopProxyFactory must not be null");
this.aopProxyFactory = aopProxyFactory;
}
publicAopProxyFactorygetAopProxyFactory() {
returnthis.aopProxyFactory;
}
publicvoidaddListener(AdvisedSupportListenerlistener) {
Assert.notNull(listener, "AdvisedSupportListener must not be null");
this.listeners.add(listener);
}
publicvoidremoveListener(AdvisedSupportListenerlistener) {
Assert.notNull(listener, "AdvisedSupportListener must not be null");
this.listeners.remove(listener);
}
protectedfinalsynchronizedAopProxycreateAopProxy() {
if (!this.active) {
activate();
}
returngetAopProxyFactory().createAopProxy(this);
}
privatevoidactivate() {
this.active = true;
for (AdvisedSupportListenerlistener : this.listeners) {
listener.activated(this);
}
}
@OverrideprotectedvoidadviceChanged() {
super.adviceChanged();
synchronized (this) {
if (this.active) {
for (AdvisedSupportListenerlistener : this.listeners) {
listener.adviceChanged(this);
}
}
}
}
protectedfinalsynchronizedbooleanisActive() {
returnthis.active;
}
}
ProxyFactoryBean.java
packageorg.springframework.aop.framework;
@SuppressWarnings("serial")
publicclassProxyFactoryBeanextendsProxyCreatorSupportimplementsFactoryBean<Object>, BeanClassLoaderAware, BeanFactoryAware {
/** * This suffix in a value in an interceptor list indicates to expand globals. */publicstaticfinalStringGLOBAL_SUFFIX = "*";
protectedfinalLoglogger = LogFactory.getLog(getClass());
privateString[] interceptorNames;
privateStringtargetName;
privatebooleanautodetectInterfaces = true;
privatebooleansingleton = true;
privateAdvisorAdapterRegistryadvisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();
privatebooleanfreezeProxy = false;
privatetransientClassLoaderproxyClassLoader = ClassUtils.getDefaultClassLoader();
privatetransientbooleanclassLoaderConfigured = false;
privatetransientBeanFactorybeanFactory;
privatebooleanadvisorChainInitialized = false;
privateObjectsingletonInstance;
publicvoidsetProxyInterfaces(Class<?>[] proxyInterfaces) throwsClassNotFoundException {
setInterfaces(proxyInterfaces);
}
publicvoidsetInterceptorNames(String... interceptorNames) {
this.interceptorNames = interceptorNames;
}
publicvoidsetTargetName(StringtargetName) {
this.targetName = targetName;
}
publicvoidsetAutodetectInterfaces(booleanautodetectInterfaces) {
this.autodetectInterfaces = autodetectInterfaces;
}
publicvoidsetSingleton(booleansingleton) {
this.singleton = singleton;
}
publicvoidsetAdvisorAdapterRegistry(AdvisorAdapterRegistryadvisorAdapterRegistry) {
this.advisorAdapterRegistry = advisorAdapterRegistry;
}
@OverridepublicvoidsetFrozen(booleanfrozen) {
this.freezeProxy = frozen;
}
publicvoidsetProxyClassLoader(ClassLoaderclassLoader) {
this.proxyClassLoader = classLoader;
this.classLoaderConfigured = (classLoader != null);
}
@OverridepublicvoidsetBeanClassLoader(ClassLoaderclassLoader) {
if (!this.classLoaderConfigured) {
this.proxyClassLoader = classLoader;
}
}
@OverridepublicvoidsetBeanFactory(BeanFactorybeanFactory) {
this.beanFactory = beanFactory;
checkInterceptorNames();
}
@OverridepublicObjectgetObject() throwsBeansException {
initializeAdvisorChain();
if (isSingleton()) {
returngetSingletonInstance();
}
else {
if (this.targetName == null) {
logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
"Enable prototype proxies by setting the 'targetName' property.");
}
returnnewPrototypeInstance();
}
}
@OverridepublicClass<?> getObjectType() {
synchronized (this) {
if (this.singletonInstance != null) {
returnthis.singletonInstance.getClass();
}
}
Class<?>[] ifcs = getProxiedInterfaces();
if (ifcs.length == 1) {
returnifcs[0];
}
elseif (ifcs.length > 1) {
returncreateCompositeInterface(ifcs);
}
elseif (this.targetName != null && this.beanFactory != null) {
returnthis.beanFactory.getType(this.targetName);
}
else {
returngetTargetClass();
}
}
@OverridepublicbooleanisSingleton() {
returnthis.singleton;
}
protectedClass<?> createCompositeInterface(Class<?>[] interfaces) {
returnClassUtils.createCompositeInterface(interfaces, this.proxyClassLoader);
}
privatesynchronizedObjectgetSingletonInstance() {
if (this.singletonInstance == null) {
this.targetSource = freshTargetSource();
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// Rely on AOP infrastructure to tell us what interfaces to proxy.Class<?> targetClass = getTargetClass();
if (targetClass == null) {
thrownewFactoryBeanNotInitializedException("Cannot determine target class for proxy");
}
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
// Initialize the shared singleton instance.super.setFrozen(this.freezeProxy);
this.singletonInstance = getProxy(createAopProxy());
}
returnthis.singletonInstance;
}
privatesynchronizedObjectnewPrototypeInstance() {
// In the case of a prototype, we need to give the proxy// an independent instance of the configuration.// In this case, no proxy will have an instance of this object's configuration,// but will have an independent copy.if (logger.isTraceEnabled()) {
logger.trace("Creating copy of prototype ProxyFactoryBean config: " + this);
}
ProxyCreatorSupportcopy = newProxyCreatorSupport(getAopProxyFactory());
// The copy needs a fresh advisor chain, and a fresh TargetSource.TargetSourcetargetSource = freshTargetSource();
copy.copyConfigurationFrom(this, targetSource, freshAdvisorChain());
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// Rely on AOP infrastructure to tell us what interfaces to proxy.copy.setInterfaces(
ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass(), this.proxyClassLoader));
}
copy.setFrozen(this.freezeProxy);
if (logger.isTraceEnabled()) {
logger.trace("Using ProxyCreatorSupport copy: " + copy);
}
returngetProxy(copy.createAopProxy());
}
protectedObjectgetProxy(AopProxyaopProxy) {
returnaopProxy.getProxy(this.proxyClassLoader);
}
privatevoidcheckInterceptorNames() {
if (!ObjectUtils.isEmpty(this.interceptorNames)) {
StringfinalName = this.interceptorNames[this.interceptorNames.length - 1];
if (this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
// The last name in the chain may be an Advisor/Advice or a target/TargetSource.// Unfortunately we don't know; we must look at type of the bean.if (!finalName.endsWith(GLOBAL_SUFFIX) && !isNamedBeanAnAdvisorOrAdvice(finalName)) {
// The target isn't an interceptor.this.targetName = finalName;
if (logger.isDebugEnabled()) {
logger.debug("Bean with name '" + finalName + "' concluding interceptor chain " +
"is not an advisor class: treating it as a target or TargetSource");
}
String[] newNames = newString[this.interceptorNames.length - 1];
System.arraycopy(this.interceptorNames, 0, newNames, 0, newNames.length);
this.interceptorNames = newNames;
}
}
}
}
privatebooleanisNamedBeanAnAdvisorOrAdvice(StringbeanName) {
Class<?> namedBeanClass = this.beanFactory.getType(beanName);
if (namedBeanClass != null) {
return (Advisor.class.isAssignableFrom(namedBeanClass) || Advice.class.isAssignableFrom(namedBeanClass));
}
// Treat it as an target bean if we can't tell.if (logger.isDebugEnabled()) {
logger.debug("Could not determine type of bean with name '" + beanName +
"' - assuming it is neither an Advisor nor an Advice");
}
returnfalse;
}
privatesynchronizedvoidinitializeAdvisorChain() throwsAopConfigException, BeansException {
if (this.advisorChainInitialized) {
return;
}
if (!ObjectUtils.isEmpty(this.interceptorNames)) {
if (this.beanFactory == null) {
thrownewIllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
}
// Globals can't be last unless we specified a targetSource using the property...if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
thrownewAopConfigException("Target required after globals");
}
// Materialize interceptor chain from bean names.for (Stringname : this.interceptorNames) {
if (logger.isTraceEnabled()) {
logger.trace("Configuring advisor or advice '" + name + "'");
}
if (name.endsWith(GLOBAL_SUFFIX)) {
if (!(this.beanFactoryinstanceofListableBeanFactory)) {
thrownewAopConfigException(
"Can only use global advisors or interceptors with a ListableBeanFactory");
}
addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
}
else {
// If we get here, we need to add a named interceptor.// We must check if it's a singleton or prototype.Objectadvice;
if (this.singleton || this.beanFactory.isSingleton(name)) {
// Add the real Advisor/Advice to the chain.advice = this.beanFactory.getBean(name);
}
else {
// It's a prototype Advice or Advisor: replace with a prototype.// Avoid unnecessary creation of prototype bean just for advisor chain initialization.advice = newPrototypePlaceholderAdvisor(name);
}
addAdvisorOnChainCreation(advice, name);
}
}
}
this.advisorChainInitialized = true;
}
privateList<Advisor> freshAdvisorChain() {
Advisor[] advisors = getAdvisors();
List<Advisor> freshAdvisors = newArrayList<Advisor>(advisors.length);
for (Advisoradvisor : advisors) {
if (advisorinstanceofPrototypePlaceholderAdvisor) {
PrototypePlaceholderAdvisorpa = (PrototypePlaceholderAdvisor) advisor;
if (logger.isDebugEnabled()) {
logger.debug("Refreshing bean named '" + pa.getBeanName() + "'");
}
// Replace the placeholder with a fresh prototype instance resulting// from a getBean() lookupif (this.beanFactory == null) {
thrownewIllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
"- cannot resolve prototype advisor '" + pa.getBeanName() + "'");
}
Objectbean = this.beanFactory.getBean(pa.getBeanName());
AdvisorrefreshedAdvisor = namedBeanToAdvisor(bean);
freshAdvisors.add(refreshedAdvisor);
}
else {
// Add the shared instance.freshAdvisors.add(advisor);
}
}
returnfreshAdvisors;
}
privatevoidaddGlobalAdvisor(ListableBeanFactorybeanFactory, Stringprefix) {
String[] globalAdvisorNames =
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, Advisor.class);
String[] globalInterceptorNames =
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, Interceptor.class);
List<Object> beans = newArrayList<Object>(globalAdvisorNames.length + globalInterceptorNames.length);
Map<Object, String> names = newHashMap<Object, String>(beans.size());
for (Stringname : globalAdvisorNames) {
Objectbean = beanFactory.getBean(name);
beans.add(bean);
names.put(bean, name);
}
for (Stringname : globalInterceptorNames) {
Objectbean = beanFactory.getBean(name);
beans.add(bean);
names.put(bean, name);
}
AnnotationAwareOrderComparator.sort(beans);
for (Objectbean : beans) {
Stringname = names.get(bean);
if (name.startsWith(prefix)) {
addAdvisorOnChainCreation(bean, name);
}
}
}
privatevoidaddAdvisorOnChainCreation(Objectnext, Stringname) {
// We need to convert to an Advisor if necessary so that our source reference// matches what we find from superclass interceptors.Advisoradvisor = namedBeanToAdvisor(next);
if (logger.isTraceEnabled()) {
logger.trace("Adding advisor with name '" + name + "'");
}
addAdvisor(advisor);
}
privateTargetSourcefreshTargetSource() {
if (this.targetName == null) {
if (logger.isTraceEnabled()) {
logger.trace("Not refreshing target: Bean name not specified in 'interceptorNames'.");
}
returnthis.targetSource;
}
else {
if (this.beanFactory == null) {
thrownewIllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
"- cannot resolve target with name '" + this.targetName + "'");
}
if (logger.isDebugEnabled()) {
logger.debug("Refreshing target with name '" + this.targetName + "'");
}
Objecttarget = this.beanFactory.getBean(this.targetName);
return (targetinstanceofTargetSource ? (TargetSource) target : newSingletonTargetSource(target));
}
}
privateAdvisornamedBeanToAdvisor(Objectnext) {
try {
returnthis.advisorAdapterRegistry.wrap(next);
}
catch (UnknownAdviceTypeExceptionex) {
// We expected this to be an Advisor or Advice,// but it wasn't. This is a configuration error.thrownewAopConfigException("Unknown advisor type " + next.getClass() +
"; Can only include Advisor or Advice type beans in interceptorNames chain except for last entry," +
"which may also be target or TargetSource", ex);
}
}
@OverrideprotectedvoidadviceChanged() {
super.adviceChanged();
if (this.singleton) {
logger.debug("Advice has changed; recaching singleton instance");
synchronized (this) {
this.singletonInstance = null;
}
}
}
//---------------------------------------------------------------------// Serialization support//---------------------------------------------------------------------privatevoidreadObject(ObjectInputStreamois) throwsIOException, ClassNotFoundException {
// Rely on default serialization; just initialize state after deserialization.ois.defaultReadObject();
// Initialize transient fields.this.proxyClassLoader = ClassUtils.getDefaultClassLoader();
}
privatestaticclassPrototypePlaceholderAdvisorimplementsAdvisor, Serializable {
privatefinalStringbeanName;
privatefinalStringmessage;
publicPrototypePlaceholderAdvisor(StringbeanName) {
this.beanName = beanName;
this.message = "Placeholder for prototype Advisor/Advice with bean name '" + beanName + "'";
}
publicStringgetBeanName() {
returnthis.beanName;
}
@OverridepublicAdvicegetAdvice() {
thrownewUnsupportedOperationException("Cannot invoke methods: " + this.message);
}
@OverridepublicbooleanisPerInstance() {
thrownewUnsupportedOperationException("Cannot invoke methods: " + this.message);
}
@OverridepublicStringtoString() {
returnthis.message;
}
}
}