`
lovnet
  • 浏览: 6694331 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

Bean第一次从容器获取的时候,如果bean配置了lookup-method,那么就使用了cglib来进行调用方法转换

 
阅读更多

Bean第一次从容器获取的时候,如果bean配置了lookup-method,那么就使用了cglib来进行调用方法转换:


我们默认的容器DefaultListableBeanFactory,其中的getBean加载的时候会走到下面的代码:


org.springframework.beans.factory.support.SimpleInstantiationStrategy:

	public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {
		// Don't override the class with CGLIB if no overrides.
		if (beanDefinition.getMethodOverrides().isEmpty()) {
			Constructor<?> constructorToUse;
			synchronized (beanDefinition.constructorArgumentLock) {
				constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod;
				if (constructorToUse == null) {
					final Class clazz = beanDefinition.getBeanClass();
					if (clazz.isInterface()) {
						throw new BeanInstantiationException(clazz, "Specified class is an interface");
					}
					try {
						if (System.getSecurityManager() != null) {
							constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor>() {
								public Constructor run() throws Exception {
									return clazz.getDeclaredConstructor((Class[]) null);
								}
							});
						}
						else {
							constructorToUse =	clazz.getDeclaredConstructor((Class[]) null);
						}
						beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse;
					}
					catch (Exception ex) {
						throw new BeanInstantiationException(clazz, "No default constructor found", ex);
					}
				}
			}
			return BeanUtils.instantiateClass(constructorToUse);
		}
		else {
			// Must generate CGLIB subclass.
			return instantiateWithMethodInjection(beanDefinition, beanName, owner);
		}
	}

那么在通过BeanDefinition创建Bean的时候,进行了beanDefinition.getMethodOverrides().isEmpty()判断,是通过cglib还是BeanUtils进行。
那么这个判断什么含义呢?
看我们dom树解析代码如下:
org.springframework.beans.factory.xml.BeanDefinitionParserDelegate:
	public static final String LOOKUP_METHOD_ELEMENT = "lookup-method";

	public static final String REPLACED_METHOD_ELEMENT = "replaced-method";
	
	/**
	 * Parse lookup-override sub-elements of the given bean element.
	 */
	public void parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides) {
		NodeList nl = beanEle.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (isCandidateElement(node) && nodeNameEquals(node, LOOKUP_METHOD_ELEMENT)) {
				Element ele = (Element) node;
				String methodName = ele.getAttribute(NAME_ATTRIBUTE);
				String beanRef = ele.getAttribute(BEAN_ELEMENT);
				LookupOverride override = new LookupOverride(methodName, beanRef);
				override.setSource(extractSource(ele));
				overrides.addOverride(override);
			}
		}
	}

<!-- 
Element : lookup-method
A lookup method causes the IoC container to override the given method and return the bean with the 
 name given in the bean attribute. This is a form of Method Injection. It is particularly useful as an 
 alternative to implementing the BeanFactoryAware interface, in order to be able to make getBean() 
 calls for non-singleton instances at runtime. In this case, Method Injection is a less invasive alternative.
-->
<bean class="...">
        <lookup-method bean="" name=""/>
</bean>

也就是配置了lookup-method的时候用cglib,因为要借助cglib来替换方法。
具体的cglib的操作是通过filter判断来调用什么代理返回形式:

		private class CallbackFilterImpl extends CglibIdentitySupport implements CallbackFilter {
			
			public int accept(Method method) {
				MethodOverride methodOverride = beanDefinition.getMethodOverrides().getOverride(method);
				if (logger.isTraceEnabled()) {
					logger.trace("Override for '" + method.getName() + "' is [" + methodOverride + "]");
				}
				if (methodOverride == null) {
					return PASSTHROUGH;
				}
				else if (methodOverride instanceof LookupOverride) {
					return LOOKUP_OVERRIDE;
				}
				else if (methodOverride instanceof ReplaceOverride) {
					return METHOD_REPLACER;
				}
				throw new UnsupportedOperationException(
						"Unexpected MethodOverride subclass: " + methodOverride.getClass().getName());
			}
		}


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics