下面列出了怎么用java.beans.Introspector的API类实例代码及写法,或者点击链接到github查看源代码。
protected Map<String, ?> pojoToMap(final Object pojo) {
Map<String, Object> map = new HashMap<String, Object>();
try {
final BeanInfo beanInfo = Introspector.getBeanInfo(pojo.getClass());
PropertyDescriptor[] propertyDescriptors = beanInfo
.getPropertyDescriptors();
for (PropertyDescriptor pd : propertyDescriptors) {
if (!isIgnorable(pd)) {
map.put(pd.getName(), pd.getReadMethod().invoke(pojo));
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return map;
}
private static void test(Class<?> type, Class<?> expected) {
Class<?> actual;
try {
actual = Introspector.getBeanInfo(type).getBeanDescriptor().getCustomizerClass();
}
catch (IntrospectionException exception) {
throw new Error("unexpected error", exception);
}
if (actual != expected) {
StringBuilder sb = new StringBuilder();
sb.append("bean ").append(type).append(": ");
if (expected != null) {
sb.append("expected ").append(expected);
if (actual != null) {
sb.append(", but ");
}
}
if (actual != null) {
sb.append("found ").append(actual);
}
throw new Error(sb.toString());
}
}
public static void main(String[] args) throws IntrospectionException {
StringBuilder sb = null;
if (args.length > 0) {
if (args[0].equals("show")) {
sb = new StringBuilder(65536);
}
}
Introspector.flushCaches();
int count = (sb != null) ? 10 : 100;
long time = -System.currentTimeMillis();
for (int i = 0; i < count; i++) {
test(sb);
test(sb);
Introspector.flushCaches();
}
time += System.currentTimeMillis();
System.out.println("Time (average): " + time / count);
}
private static PropertyDescriptor[] getPropertyDescriptors(Object object) {
Class type = object.getClass();
synchronized (System.out) {
System.out.println(type);
ClassLoader loader = type.getClassLoader();
while (loader != null) {
System.out.println(" - loader: " + loader);
loader = loader.getParent();
}
}
try {
return Introspector.getBeanInfo(type).getPropertyDescriptors();
} catch (IntrospectionException exception) {
throw new Error("unexpected exception", exception);
}
}
public void testMockIncompatibleAllSetterAndGetterBean() throws Exception {
Class<?> beanClass = MockIncompatibleAllSetterAndGetterBean.class;
BeanInfo beanInfo = Introspector.getBeanInfo(beanClass);
PropertyDescriptor pd = null;
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
for (int i = 0; i < pds.length; i++) {
pd = pds[i];
if (pd.getName().equals("data")) {
break;
}
}
assertNotNull(pd);
assertTrue(pd instanceof IndexedPropertyDescriptor);
IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd;
assertNull(ipd.getReadMethod());
assertNull(ipd.getWriteMethod());
Method indexedReadMethod = beanClass.getMethod("getData",
new Class[] { int.class });
Method indexedWriteMethod = beanClass.getMethod("setData", new Class[] {
int.class, int.class });
assertEquals(indexedReadMethod, ipd.getIndexedReadMethod());
assertEquals(indexedWriteMethod, ipd.getIndexedWriteMethod());
}
private static PropertyDescriptor[] getPropertyDescriptorsIfCache(Class clazz) throws IllegalStateException{
PropertyDescriptor[] result = PROPERTY_DESCRIPTOR_CACHE_MAP.get(clazz);
if(result == null) {
try {
BeanInfo beanInfo = Introspector.getBeanInfo(clazz, Object.class, Introspector.USE_ALL_BEANINFO);
PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
if(descriptors != null){
result = descriptors;
}else {
result = EMPTY_DESCRIPTOR_ARRAY;
}
PROPERTY_DESCRIPTOR_CACHE_MAP.put(clazz,result);
} catch (IntrospectionException e) {
throw new IllegalStateException("getPropertyDescriptors error. class=" + clazz+e,e);
}
// TODO: 1月28日 028 getPropertyDescriptorsIfCache
// skip GenericTypeAwarePropertyDescriptor leniently resolves a set* write method
// against a declared read method, so we prefer read method descriptors here.
}
return result;
}
private Map<String, Object> toMap() {
try {
Map<String, Object> params = new HashMap<>();
ArrayList<String> availableProperties = new ArrayList<>();
availableProperties.addAll(classesIntrospection(this.getClass()));
BeanInfo info = Introspector.getBeanInfo(this.getClass());
for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
Method reader = pd.getReadMethod();
if (reader != null && availableProperties.contains(pd.getName())) {
params.put(pd.getName(), reader.invoke(this));
}
}
return params;
} catch (IntrospectionException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
return Collections.emptyMap();
}
}
public static void main(String[] args) throws IntrospectionException {
StringBuilder sb = null;
if (args.length > 0) {
if (args[0].equals("show")) {
sb = new StringBuilder(65536);
}
}
Introspector.flushCaches();
int count = (sb != null) ? 10 : 100;
long time = -System.currentTimeMillis();
for (int i = 0; i < count; i++) {
test(sb);
test(sb);
Introspector.flushCaches();
}
time += System.currentTimeMillis();
System.out.println("Time (average): " + time / count);
}
@Test
public void nonStandardReadMethodAndStandardWriteMethod() throws IntrospectionException {
@SuppressWarnings("unused") class C {
public void getFoo() { }
public void setFoo(String foo) { }
}
BeanInfo bi = Introspector.getBeanInfo(C.class);
BeanInfo ebi = new ExtendedBeanInfo(bi);
assertThat(hasReadMethodForProperty(bi, "foo"), is(false));
assertThat(hasWriteMethodForProperty(bi, "foo"), is(true));
assertThat(hasReadMethodForProperty(ebi, "foo"), is(false));
assertThat(hasWriteMethodForProperty(ebi, "foo"), is(true));
}
private static void test(Class<?> type, Class<?> expected) {
Class<?> actual;
try {
actual = Introspector.getBeanInfo(type).getBeanDescriptor().getCustomizerClass();
}
catch (IntrospectionException exception) {
throw new Error("unexpected error", exception);
}
if (actual != expected) {
StringBuilder sb = new StringBuilder();
sb.append("bean ").append(type).append(": ");
if (expected != null) {
sb.append("expected ").append(expected);
if (actual != null) {
sb.append(", but ");
}
}
if (actual != null) {
sb.append("found ").append(actual);
}
throw new Error(sb.toString());
}
}
public Collection<Class<?>> extractDataClasses(Collection<Class<?>> input, String targetDirectory) {
Set<Class<?>> dataModelClasses = new HashSet<>();
for (Class<?> modelClazz : input) {
try {
BeanInfo beanInfo = Introspector.getBeanInfo(modelClazz);
for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) {
Class<?> propertyType = pd.getPropertyType();
if (propertyType.getCanonicalName().startsWith("java.lang")
|| propertyType.getCanonicalName().equals(Date.class.getCanonicalName())) {
continue;
}
dataModelClasses.add(propertyType);
}
generateModelClassProto(modelClazz, targetDirectory);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return dataModelClasses;
}
/**
* Gets the properties from a Java Bean and returns them in a Map of String
* name/value pairs. Because this method has to know how to convert a
* bean property into a String value, only a few bean property
* types are supported. They are: String, boolean, int, long, float, double,
* Color, and Class.
*
* @param bean a Java Bean to get properties from.
* @return a Map of all properties as String name/value pairs.
*/
public static Map<String, String> getProperties(Object bean) {
Map<String, String> properties = new HashMap<>();
try {
BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
// Loop through all properties of the bean.
PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
String [] names = new String[descriptors.length];
for (int i=0; i<names.length; i++) {
// Determine the property name.
String name = descriptors[i].getName();
//Class type = descriptors[i].getPropertyType();
// Decode the property value using the property type and
// encoded String value.
Object value = descriptors[i].getReadMethod().invoke(bean,(java.lang.Object[]) null);
// Add to Map, encoding the value as a String.
properties.put(name, encode(value));
}
}
catch (Exception e) {
Log.error(e.getMessage(), e);
}
return properties;
}
private static PropertyDescriptor[] getPropertyDescriptors(Object object) {
Class type = object.getClass();
synchronized (System.out) {
System.out.println(type);
ClassLoader loader = type.getClassLoader();
while (loader != null) {
System.out.println(" - loader: " + loader);
loader = loader.getParent();
}
}
try {
return Introspector.getBeanInfo(type).getPropertyDescriptors();
} catch (IntrospectionException exception) {
throw new Error("unexpected exception", exception);
}
}
public TypeReflector(JavaType javaType) {
this.javaType = assertNotNull(javaType, "javaType");
try {
PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(javaType.getRawClass()).getPropertyDescriptors();
for (PropertyDescriptor descriptor : propertyDescriptors) {
if (descriptor.getReadMethod() == null || descriptor.getWriteMethod() == null) {
continue; // TODO: Warn? Error?
}
this.propertyDescriptors.add(descriptor);
this.setters.put(descriptor.getName(), makeSetter(descriptor));
this.getters.put(descriptor.getName(), makeGetter(descriptor));
}
} catch (IntrospectionException ex) {
throw new IllegalArgumentException("Could not introspect bean: " + javaType.getTypeName(), ex);
}
this.propertyDescriptorIndex = propertyDescriptors.stream().collect(Collectors.toMap(
PropertyDescriptor::getName,
p -> p
));
}
public static void main(String[] args) throws IntrospectionException {
if (!BeanUtils.findPropertyDescriptor(MyBean.class, "test").isBound()) {
throw new Error("a simple property is not bound");
}
if (!BeanUtils.findPropertyDescriptor(MyBean.class, "list").isBound()) {
throw new Error("a generic property is not bound");
}
if (!BeanUtils.findPropertyDescriptor(MyBean.class, "readOnly").isBound()) {
throw new Error("a read-only property is not bound");
}
PropertyDescriptor[] pds = Introspector.getBeanInfo(MyBean.class, BaseBean.class).getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
if (pd.getName().equals("test") && pd.isBound()) {
throw new Error("a simple property is bound without superclass");
}
}
}
@Test
public void nonPublicStandardReadAndWriteMethods() throws Exception {
@SuppressWarnings("unused") class C {
String getFoo() { return null; }
C setFoo(String foo) { return this; }
}
BeanInfo bi = Introspector.getBeanInfo(C.class);
BeanInfo ebi = new ExtendedBeanInfo(bi);
assertThat(hasReadMethodForProperty(bi, "foo"), is(false));
assertThat(hasWriteMethodForProperty(bi, "foo"), is(false));
assertThat(hasReadMethodForProperty(ebi, "foo"), is(false));
assertThat(hasWriteMethodForProperty(ebi, "foo"), is(false));
}
/**
* Sets the value for a specified parameter.
*
* @param paramaterName the name for the parameteer
* @param parameterValue the value the parameter will receive
*/
@Override
public void setParameterValue(String paramaterName, Object parameterValue)
throws ResourceInstantiationException{
// get the beaninfo for the resource bean, excluding data about Object
BeanInfo resBeanInf = null;
try {
resBeanInf = Introspector.getBeanInfo(this.getClass(), Object.class);
} catch(Exception e) {
throw new ResourceInstantiationException(
"Couldn't get bean info for resource " + this.getClass().getName()
+ Strings.getNl() + "Introspector exception was: " + e
);
}
AbstractResource.setParameterValue(this, resBeanInf, paramaterName, parameterValue);
}
public static void main(String[] args) throws IntrospectionException {
StringBuilder sb = null;
if (args.length > 0) {
if (args[0].equals("show")) {
sb = new StringBuilder(65536);
}
}
Introspector.flushCaches();
int count = (sb != null) ? 10 : 100;
long time = -System.currentTimeMillis();
for (int i = 0; i < count; i++) {
test(sb);
test(sb);
Introspector.flushCaches();
}
time += System.currentTimeMillis();
System.out.println("Time (average): " + time / count);
}
private Map<String, Object> toMap(Object bean) {
if (bean == null) {
return null;
}
Map<String, Object> map = new HashMap<String, Object>();
try {
BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor property : propertyDescriptors) {
String key = property.getName();
// 过滤class属性,否则输出结果会有 class 属性
if (!key.equals("class")) {
// 得到property对应的getter方法
Method getter = property.getReadMethod();
Object value = getter.invoke(bean);
map.put(key, value);
}
}
} catch (Exception e) {
System.out.println("transBean2Map Error " + e);
}
return map;
}
public static void main(String[] args) throws IntrospectionException {
if (!BeanUtils.findPropertyDescriptor(MyBean.class, "test").isBound()) {
throw new Error("a simple property is not bound");
}
if (!BeanUtils.findPropertyDescriptor(MyBean.class, "list").isBound()) {
throw new Error("a generic property is not bound");
}
if (!BeanUtils.findPropertyDescriptor(MyBean.class, "readOnly").isBound()) {
throw new Error("a read-only property is not bound");
}
PropertyDescriptor[] pds = Introspector.getBeanInfo(MyBean.class, BaseBean.class).getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
if (pd.getName().equals("test") && pd.isBound()) {
throw new Error("a simple property is bound without superclass");
}
}
}
private static void test(Class<?> type, Class<?> expected) {
Class<?> actual;
try {
actual = Introspector.getBeanInfo(type).getBeanDescriptor().getCustomizerClass();
}
catch (IntrospectionException exception) {
throw new Error("unexpected error", exception);
}
if (actual != expected) {
StringBuilder sb = new StringBuilder();
sb.append("bean ").append(type).append(": ");
if (expected != null) {
sb.append("expected ").append(expected);
if (actual != null) {
sb.append(", but ");
}
}
if (actual != null) {
sb.append("found ").append(actual);
}
throw new Error(sb.toString());
}
}
/** Based on names of getter and setter resolves the name of the property.
* @return Name of the property
*/
String findPropertyName() {
String methodName = null;
if ( getterMethod != null )
methodName = nameAsString(getterMethod);
else if ( setterMethod != null )
methodName = nameAsString(setterMethod);
else {
return null;
}
return methodName.startsWith( IS_PREFIX ) ? // NOI18N
Introspector.decapitalize( methodName.substring(2) ) :
Introspector.decapitalize( methodName.substring(3) );
}
XMLDataWriter(Object bean, Writer out, ExportConfig config) throws IOException {
Class c=bean.getClass();
while (c.isAnonymousClass())
c = c.getSuperclass();
name = Introspector.decapitalize(c.getSimpleName());
this.out = out;
this.config = config;
this.isArray.push(false);
this.exportConfig = config;
// TODO: support pretty printing
}
/**
* Returns an array of event set descriptors for specified class.
*
* @param type the class to introspect
* @return an array of event set descriptors
*/
public static EventSetDescriptor[] getEventSetDescriptors(Class type) {
try {
return Introspector.getBeanInfo(type).getEventSetDescriptors();
} catch (IntrospectionException exception) {
throw new Error("unexpected exception", exception);
}
}
public static void main(String[] args) throws Exception {
printMemory("Start Memory");
int introspected = 200;
for (int i = 0; i < introspected; i++) {
ClassLoader cl = new SimpleClassLoader();
Class type = cl.loadClass("Bean");
type.newInstance();
// The methods and the bean info should be cached
BeanInfo info = Introspector.getBeanInfo(type);
cl = null;
type = null;
info = null;
System.gc();
}
System.runFinalization();
printMemory("End Memory");
int finalized = SimpleClassLoader.numFinalizers;
System.out.println(introspected + " classes introspected");
System.out.println(finalized + " classes finalized");
// good if at least half of the finalizers are run
if (finalized < (introspected >> 1)) {
throw new Error("ClassLoaders not finalized: " + finalized);
}
}
private static void test() {
test("Bean", "Bean2", "Bean3", "Bean4");
test("Bean4", "Bean", "Bean2", "Bean3");
test("Bean3", "Bean4", "Bean", "Bean2");
test("Bean2", "Bean3", "Bean4", "Bean");
Introspector.flushCaches();
}
/**
* If the base object is not null, returns an Iterator containing the set of JavaBeans
* properties available on the given object. Otherwise, returns null. The Iterator returned must
* contain zero or more instances of java.beans.FeatureDescriptor. Each info object contains
* information about a property in the bean, as obtained by calling the
* BeanInfo.getPropertyDescriptors method. The FeatureDescriptor is initialized using the same
* fields as are present in the PropertyDescriptor, with the additional required named
* attributes "type" and "resolvableAtDesignTime" set as follows:
* <ul>
* <li>{@link ELResolver#TYPE} - The runtime type of the property, from
* PropertyDescriptor.getPropertyType().</li>
* <li>{@link ELResolver#RESOLVABLE_AT_DESIGN_TIME} - true.</li>
* </ul>
*
* @param context
* The context of this evaluation.
* @param base
* The bean to analyze.
* @return An Iterator containing zero or more FeatureDescriptor objects, each representing a
* property on this bean, or null if the base object is null.
*/
@Override
public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
if (isResolvable(base)) {
final PropertyDescriptor[] properties;
try {
properties = Introspector.getBeanInfo(base.getClass()).getPropertyDescriptors();
} catch (IntrospectionException e) {
return Collections.<FeatureDescriptor> emptyList().iterator();
}
return new Iterator<FeatureDescriptor>() {
int next = 0;
public boolean hasNext() {
return properties != null && next < properties.length;
}
public FeatureDescriptor next() {
PropertyDescriptor property = properties[next++];
FeatureDescriptor feature = new FeatureDescriptor();
feature.setDisplayName(property.getDisplayName());
feature.setName(property.getName());
feature.setShortDescription(property.getShortDescription());
feature.setExpert(property.isExpert());
feature.setHidden(property.isHidden());
feature.setPreferred(property.isPreferred());
feature.setValue(TYPE, property.getPropertyType());
feature.setValue(RESOLVABLE_AT_DESIGN_TIME, true);
return feature;
}
public void remove() {
throw new UnsupportedOperationException("cannot remove");
}
};
}
return null;
}
public static BeanInfo getBeanInfo(Class<?> key) {
return beanInfoCache.get(key, () -> {
BeanInfo info = Introspector.getBeanInfo(key);
Introspector.flushCaches();
return info;
});
}
private static Method getSetterMethod(Class<?> clazz, String name) {
Method[] methods = clazz.getMethods();
for (Method method : methods) {
String methodName = method.getName();
if (methodName.startsWith(SETTER_METHOD_PREFIX) && method.getParameterTypes().length == 1) {
if (Introspector.decapitalize(methodName.substring(SETTER_METHOD_PREFIX_LENGTH)).equals(name)) {
return method;
}
}
}
return null;
}
public static void main(String[] args) throws Exception {
long time = System.nanoTime();
for (Class type : TYPES) {
Introspector.getBeanInfo(type);
}
time -= System.nanoTime();
System.out.println("Time (ms): " + (-time / 1000000));
}