1 16 17 package org.springframework.beans.factory.support; 18 19 import java.lang.reflect.Constructor ; 20 import java.lang.reflect.Method ; 21 22 import net.sf.cglib.proxy.Callback; 23 import net.sf.cglib.proxy.CallbackFilter; 24 import net.sf.cglib.proxy.Enhancer; 25 import net.sf.cglib.proxy.MethodInterceptor; 26 import net.sf.cglib.proxy.MethodProxy; 27 import net.sf.cglib.proxy.NoOp; 28 import org.apache.commons.logging.Log; 29 import org.apache.commons.logging.LogFactory; 30 31 import org.springframework.beans.factory.BeanFactory; 32 33 44 public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationStrategy { 45 46 50 private static final int PASSTHROUGH = 0; 51 52 56 private static final int LOOKUP_OVERRIDE = 1; 57 58 62 private static final int METHOD_REPLACER = 2; 63 64 65 protected Object instantiateWithMethodInjection( 66 RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) { 67 68 return new CglibSubclassCreator(beanDefinition, owner).instantiate(null, null); 70 } 71 72 protected Object instantiateWithMethodInjection( 73 RootBeanDefinition beanDefinition, String beanName, BeanFactory owner, 74 Constructor ctor, Object [] args) { 75 76 return new CglibSubclassCreator(beanDefinition, owner).instantiate(ctor, args); 77 } 78 79 80 83 private static class CglibSubclassCreator { 84 85 private static final Log logger = LogFactory.getLog(CglibSubclassCreator.class); 86 87 private final RootBeanDefinition beanDefinition; 88 89 private final BeanFactory owner; 90 91 public CglibSubclassCreator(RootBeanDefinition beanDefinition, BeanFactory owner) { 92 this.beanDefinition = beanDefinition; 93 this.owner = owner; 94 } 95 96 105 public Object instantiate(Constructor ctor, Object [] args) { 106 Enhancer enhancer = new Enhancer(); 107 enhancer.setSuperclass(this.beanDefinition.getBeanClass()); 108 enhancer.setCallbackFilter(new CallbackFilterImpl()); 109 enhancer.setCallbacks(new Callback[] { 110 NoOp.INSTANCE, 111 new LookupOverrideMethodInterceptor(), 112 new ReplaceOverrideMethodInterceptor() 113 }); 114 115 return (ctor == null) ? 116 enhancer.create() : 117 enhancer.create(ctor.getParameterTypes(), args); 118 } 119 120 121 126 private class CglibIdentitySupport { 127 130 protected RootBeanDefinition getBeanDefinition() { 131 return beanDefinition; 132 } 133 134 public int hashCode() { 135 return beanDefinition.hashCode(); 136 } 137 138 public boolean equals(Object other) { 139 return (other.getClass() == getClass()) && 140 ((CglibIdentitySupport) other).getBeanDefinition() == beanDefinition; 141 } 142 } 143 144 145 149 private class LookupOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor { 150 151 public Object intercept(Object obj, Method method, Object [] args, MethodProxy mp) throws Throwable { 152 LookupOverride lo = (LookupOverride) beanDefinition.getMethodOverrides().getOverride(method); 154 return owner.getBean(lo.getBeanName()); 155 } 156 } 157 158 159 163 private class ReplaceOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor { 164 165 public Object intercept(Object obj, Method method, Object [] args, MethodProxy mp) throws Throwable { 166 ReplaceOverride ro = (ReplaceOverride) beanDefinition.getMethodOverrides().getOverride(method); 167 MethodReplacer mr = (MethodReplacer) owner.getBean(ro.getMethodReplacerBeanName()); 169 return mr.reimplement(obj, method, args); 170 } 171 } 172 173 174 177 private class CallbackFilterImpl extends CglibIdentitySupport implements CallbackFilter { 178 179 public int accept(Method method) { 180 MethodOverride methodOverride = beanDefinition.getMethodOverrides().getOverride(method); 181 if (logger.isTraceEnabled()) { 182 logger.trace("Override for '" + method.getName() + "' is [" + methodOverride + "]"); 183 } 184 if (methodOverride == null) { 185 return PASSTHROUGH; 186 } 187 else if (methodOverride instanceof LookupOverride) { 188 return LOOKUP_OVERRIDE; 189 } 190 else if (methodOverride instanceof ReplaceOverride) { 191 return METHOD_REPLACER; 192 } 193 throw new UnsupportedOperationException ( 194 "Unexpected MethodOverride subclass: " + methodOverride.getClass().getName()); 195 } 196 } 197 } 198 199 } 200 | Popular Tags |