|
|
|
@ -25,7 +25,6 @@ import org.apache.commons.logging.LogFactory; |
|
|
|
import org.springframework.beans.BeanInstantiationException; |
|
|
|
import org.springframework.beans.BeanInstantiationException; |
|
|
|
import org.springframework.beans.BeanUtils; |
|
|
|
import org.springframework.beans.BeanUtils; |
|
|
|
import org.springframework.beans.factory.BeanFactory; |
|
|
|
import org.springframework.beans.factory.BeanFactory; |
|
|
|
|
|
|
|
|
|
|
|
import org.springframework.cglib.core.SpringNamingPolicy; |
|
|
|
import org.springframework.cglib.core.SpringNamingPolicy; |
|
|
|
import org.springframework.cglib.proxy.Callback; |
|
|
|
import org.springframework.cglib.proxy.Callback; |
|
|
|
import org.springframework.cglib.proxy.CallbackFilter; |
|
|
|
import org.springframework.cglib.proxy.CallbackFilter; |
|
|
|
@ -34,6 +33,7 @@ import org.springframework.cglib.proxy.Factory; |
|
|
|
import org.springframework.cglib.proxy.MethodInterceptor; |
|
|
|
import org.springframework.cglib.proxy.MethodInterceptor; |
|
|
|
import org.springframework.cglib.proxy.MethodProxy; |
|
|
|
import org.springframework.cglib.proxy.MethodProxy; |
|
|
|
import org.springframework.cglib.proxy.NoOp; |
|
|
|
import org.springframework.cglib.proxy.NoOp; |
|
|
|
|
|
|
|
import org.springframework.util.StringUtils; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Default object instantiation strategy for use in BeanFactories. |
|
|
|
* Default object instantiation strategy for use in BeanFactories. |
|
|
|
@ -89,14 +89,13 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private static class CglibSubclassCreator { |
|
|
|
private static class CglibSubclassCreator { |
|
|
|
|
|
|
|
|
|
|
|
private static final Class<?>[] CALLBACK_TYPES = new Class<?>[] { NoOp.class, |
|
|
|
private static final Class<?>[] CALLBACK_TYPES = new Class<?>[] |
|
|
|
LookupOverrideMethodInterceptor.class, ReplaceOverrideMethodInterceptor.class }; |
|
|
|
{NoOp.class, LookupOverrideMethodInterceptor.class, ReplaceOverrideMethodInterceptor.class}; |
|
|
|
|
|
|
|
|
|
|
|
private final RootBeanDefinition beanDefinition; |
|
|
|
private final RootBeanDefinition beanDefinition; |
|
|
|
|
|
|
|
|
|
|
|
private final BeanFactory owner; |
|
|
|
private final BeanFactory owner; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CglibSubclassCreator(RootBeanDefinition beanDefinition, BeanFactory owner) { |
|
|
|
CglibSubclassCreator(RootBeanDefinition beanDefinition, BeanFactory owner) { |
|
|
|
this.beanDefinition = beanDefinition; |
|
|
|
this.beanDefinition = beanDefinition; |
|
|
|
this.owner = owner; |
|
|
|
this.owner = owner; |
|
|
|
@ -113,7 +112,6 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
Object instantiate(Constructor<?> ctor, Object[] args) { |
|
|
|
Object instantiate(Constructor<?> ctor, Object[] args) { |
|
|
|
Class<?> subclass = createEnhancedSubclass(this.beanDefinition); |
|
|
|
Class<?> subclass = createEnhancedSubclass(this.beanDefinition); |
|
|
|
|
|
|
|
|
|
|
|
Object instance; |
|
|
|
Object instance; |
|
|
|
if (ctor == null) { |
|
|
|
if (ctor == null) { |
|
|
|
instance = BeanUtils.instantiate(subclass); |
|
|
|
instance = BeanUtils.instantiate(subclass); |
|
|
|
@ -123,19 +121,17 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt |
|
|
|
Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes()); |
|
|
|
Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes()); |
|
|
|
instance = enhancedSubclassConstructor.newInstance(args); |
|
|
|
instance = enhancedSubclassConstructor.newInstance(args); |
|
|
|
} |
|
|
|
} |
|
|
|
catch (Exception e) { |
|
|
|
catch (Exception ex) { |
|
|
|
throw new BeanInstantiationException(this.beanDefinition.getBeanClass(), String.format( |
|
|
|
throw new BeanInstantiationException(this.beanDefinition.getBeanClass(), String.format( |
|
|
|
"Failed to invoke construcor for CGLIB enhanced subclass [%s]", subclass.getName()), e); |
|
|
|
"Failed to invoke constructor for CGLIB enhanced subclass [%s]", subclass.getName()), ex); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// SPR-10785: set callbacks directly on the instance instead of in the
|
|
|
|
// SPR-10785: set callbacks directly on the instance instead of in the
|
|
|
|
// enhanced class (via the Enhancer) in order to avoid memory leaks.
|
|
|
|
// enhanced class (via the Enhancer) in order to avoid memory leaks.
|
|
|
|
Factory factory = (Factory) instance; |
|
|
|
Factory factory = (Factory) instance; |
|
|
|
factory.setCallbacks(new Callback[] { NoOp.INSTANCE,//
|
|
|
|
factory.setCallbacks(new Callback[] {NoOp.INSTANCE, |
|
|
|
new LookupOverrideMethodInterceptor(beanDefinition, owner),//
|
|
|
|
new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner), |
|
|
|
new ReplaceOverrideMethodInterceptor(beanDefinition, owner) }); |
|
|
|
new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)}); |
|
|
|
|
|
|
|
|
|
|
|
return instance; |
|
|
|
return instance; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -153,6 +149,7 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Class providing hashCode and equals methods required by CGLIB to |
|
|
|
* Class providing hashCode and equals methods required by CGLIB to |
|
|
|
* ensure that CGLIB doesn't generate a distinct class per bean. |
|
|
|
* ensure that CGLIB doesn't generate a distinct class per bean. |
|
|
|
@ -162,7 +159,6 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt |
|
|
|
|
|
|
|
|
|
|
|
private final RootBeanDefinition beanDefinition; |
|
|
|
private final RootBeanDefinition beanDefinition; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CglibIdentitySupport(RootBeanDefinition beanDefinition) { |
|
|
|
CglibIdentitySupport(RootBeanDefinition beanDefinition) { |
|
|
|
this.beanDefinition = beanDefinition; |
|
|
|
this.beanDefinition = beanDefinition; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -173,8 +169,8 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public boolean equals(Object other) { |
|
|
|
public boolean equals(Object other) { |
|
|
|
return other.getClass().equals(this.getClass()) |
|
|
|
return (getClass().equals(other.getClass()) && |
|
|
|
&& ((CglibIdentitySupport) other).getBeanDefinition().equals(this.getBeanDefinition()); |
|
|
|
this.beanDefinition.equals(((CglibIdentitySupport) other).beanDefinition)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
@ -183,6 +179,7 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* CGLIB callback for filtering method interception behavior. |
|
|
|
* CGLIB callback for filtering method interception behavior. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
@ -190,7 +187,6 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt |
|
|
|
|
|
|
|
|
|
|
|
private static final Log logger = LogFactory.getLog(MethodOverrideCallbackFilter.class); |
|
|
|
private static final Log logger = LogFactory.getLog(MethodOverrideCallbackFilter.class); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MethodOverrideCallbackFilter(RootBeanDefinition beanDefinition) { |
|
|
|
MethodOverrideCallbackFilter(RootBeanDefinition beanDefinition) { |
|
|
|
super(beanDefinition); |
|
|
|
super(beanDefinition); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -210,11 +206,12 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt |
|
|
|
else if (methodOverride instanceof ReplaceOverride) { |
|
|
|
else if (methodOverride instanceof ReplaceOverride) { |
|
|
|
return METHOD_REPLACER; |
|
|
|
return METHOD_REPLACER; |
|
|
|
} |
|
|
|
} |
|
|
|
throw new UnsupportedOperationException("Unexpected MethodOverride subclass: " |
|
|
|
throw new UnsupportedOperationException("Unexpected MethodOverride subclass: " + |
|
|
|
+ methodOverride.getClass().getName()); |
|
|
|
methodOverride.getClass().getName()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* CGLIB MethodInterceptor to override methods, replacing them with an |
|
|
|
* CGLIB MethodInterceptor to override methods, replacing them with an |
|
|
|
* implementation that returns a bean looked up in the container. |
|
|
|
* implementation that returns a bean looked up in the container. |
|
|
|
@ -223,7 +220,6 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt |
|
|
|
|
|
|
|
|
|
|
|
private final BeanFactory owner; |
|
|
|
private final BeanFactory owner; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LookupOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) { |
|
|
|
LookupOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) { |
|
|
|
super(beanDefinition); |
|
|
|
super(beanDefinition); |
|
|
|
this.owner = owner; |
|
|
|
this.owner = owner; |
|
|
|
@ -233,10 +229,17 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt |
|
|
|
public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable { |
|
|
|
public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable { |
|
|
|
// Cast is safe, as CallbackFilter filters are used selectively.
|
|
|
|
// Cast is safe, as CallbackFilter filters are used selectively.
|
|
|
|
LookupOverride lo = (LookupOverride) getBeanDefinition().getMethodOverrides().getOverride(method); |
|
|
|
LookupOverride lo = (LookupOverride) getBeanDefinition().getMethodOverrides().getOverride(method); |
|
|
|
return this.owner.getBean(lo.getBeanName()); |
|
|
|
Object[] argsToUse = (args.length > 0 ? args : null); // if no-arg, don't insist on args at all
|
|
|
|
|
|
|
|
if (StringUtils.hasText(lo.getBeanName())) { |
|
|
|
|
|
|
|
return this.owner.getBean(lo.getBeanName(), argsToUse); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
return this.owner.getBean(method.getReturnType(), argsToUse); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* CGLIB MethodInterceptor to override methods, replacing them with a call |
|
|
|
* CGLIB MethodInterceptor to override methods, replacing them with a call |
|
|
|
* to a generic MethodReplacer. |
|
|
|
* to a generic MethodReplacer. |
|
|
|
@ -245,7 +248,6 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt |
|
|
|
|
|
|
|
|
|
|
|
private final BeanFactory owner; |
|
|
|
private final BeanFactory owner; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ReplaceOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) { |
|
|
|
ReplaceOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) { |
|
|
|
super(beanDefinition); |
|
|
|
super(beanDefinition); |
|
|
|
this.owner = owner; |
|
|
|
this.owner = owner; |
|
|
|
@ -255,7 +257,7 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt |
|
|
|
public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable { |
|
|
|
public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable { |
|
|
|
ReplaceOverride ro = (ReplaceOverride) getBeanDefinition().getMethodOverrides().getOverride(method); |
|
|
|
ReplaceOverride ro = (ReplaceOverride) getBeanDefinition().getMethodOverrides().getOverride(method); |
|
|
|
// TODO could cache if a singleton for minor performance optimization
|
|
|
|
// TODO could cache if a singleton for minor performance optimization
|
|
|
|
MethodReplacer mr = owner.getBean(ro.getMethodReplacerBeanName(), MethodReplacer.class); |
|
|
|
MethodReplacer mr = this.owner.getBean(ro.getMethodReplacerBeanName(), MethodReplacer.class); |
|
|
|
return mr.reimplement(obj, method, args); |
|
|
|
return mr.reimplement(obj, method, args); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|