[英]ASM Dynamic Sub Class Creation - NoClassDefFoundError BeanInfo
[英]Alternate method of BeanInfo creation?
我最近将Spring应用程序从Java 1.6移到了Java 1.8。 这导致弹簧自举花费了一个数量级的时间(之前20s,现在4min)。 追查原因使我进入了为每个bean创建的CachedIntrospectionResults
类。 创建后会调用
beanInfo = (shouldIntrospectorIgnoreBeaninfoClasses ?
Introspector.getBeanInfo(beanClass, Introspector.IGNORE_ALL_BEANINFO) :
Introspector.getBeanInfo(beanClass));
内部检查器然后在java 1.6中创建bean信息,它调用
private BeanDescriptor getTargetBeanDescriptor() {
// Use explicit info, if available,
if (explicitBeanInfo != null) {
BeanDescriptor bd = explicitBeanInfo.getBeanDescriptor();
if (bd != null) {
return (bd);
}
}
// OK, fabricate a default BeanDescriptor.
return new BeanDescriptor(this.beanClass);
}
但是在Java 1.8中,它现在会调用
private BeanDescriptor getTargetBeanDescriptor() {
// Use explicit info, if available,
if (explicitBeanInfo != null) {
BeanDescriptor bd = explicitBeanInfo.getBeanDescriptor();
if (bd != null) {
return (bd);
}
}
// OK, fabricate a default BeanDescriptor.
return new BeanDescriptor(this.beanClass, findCustomizerClass(this.beanClass));
}
private static Class<?> findCustomizerClass(Class<?> type) {
String name = type.getName() + "Customizer";
try {
type = ClassFinder.findClass(name, type.getClassLoader());
// Each customizer should inherit java.awt.Component and implement java.beans.Customizer
// according to the section 9.3 of JavaBeans™ specification
if (Component.class.isAssignableFrom(type) && Customizer.class.isAssignableFrom(type)) {
return type;
}
}
catch (Exception exception) {
// ignore any exceptions
}
return null;
}
据我所知,此方法是在Java 1.7中添加的,并且由于我未定义任何定制程序类,因此它将搜索我的完整类路径,然后引发异常,最终需要花费几百毫秒的时间。 结果是每个bean初始化需要约500ms。 对启动时间的巨大打击。
我现在正在尝试寻找解决此问题的方法,
春天的文档说要实现BeanInfoFactory以便自定义beanInfo的创建。 但是我找不到任何地方能说明如何为所提供的类创建BeanInfo。
我实际上该怎么做? Introspector使用了一堆私有构造函数来构建它,所以我不能真正遵循它,而简单地返回一个空BeanInfo就会使它崩溃。 spring实际上想要beaninfo想要什么?
有任何想法吗?
通常,当您提供显式BeanInfo
,只要显式BeanInfo
返回null
,Introspector就会自动收集信息。 因此,提供一个仅返回非null
BeanDescriptor
的空BeanInfo
以禁止自动Customizer
搜索应该没有问题。
例如:
import java.beans.*;
import java.util.stream.Stream;
public class BeanInfoTest {
public static void main(String... arg) throws IntrospectionException {
BeanInfo bi=Introspector.getBeanInfo(TheComponent.class, Object.class);
System.out.println("properties: ");
Stream.of(bi.getPropertyDescriptors())
.map(p->p.getPropertyType().getSimpleName()+' '+p.getName())
.forEach(System.out::println);
}
public static class TheComponent {
String foo;
int bar;
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
public int getBar() {
return bar;
}
public void setBar(int bar) {
this.bar = bar;
}
}
public static class TheComponentBeanInfo extends SimpleBeanInfo {
/** Overridden to prevent the automated search for a Customizer */
@Override
public BeanDescriptor getBeanDescriptor() {
System.out.println("Providing my explicit BeanDescriptor");
return new BeanDescriptor(TheComponent.class);
}
}
}
将打印
Providing my explicit BeanDescriptor
properties:
int bar
String foo
因此,它使用显式BeanDescriptor
时通过自动搜索找到了属性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.