您的位置:首页 > 其它

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

2012-05-27 19:27 555 查看
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());
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐