What is introspection
In computer science, introspection refers to the ability of computer programs to check the type of objects at Run time, which can also be called run-time type checking. Introspection and reflection should not be confused. Compared with introspection, reflection goes further. It refers to the ability of a computer program to access, detect and modify its own state or behavior at Run time.
The difference between introspection and reflection
Reflection is to map various components of Java classes into corresponding Java classes in the running state, which can dynamically obtain all attributes and dynamically call any method, emphasizing the running state.
.
Introspector is a default processing method of Java language for bean class attributes and events. JavaBean is a special class, which is mainly used to transfer data information. The methods in this class are mainly used to access private fields, and the method name conforms to some naming rules. If you pass information between two modules, you can encapsulate the information into a JavaBean. This kind of object is called "value object", or "VO". There are few methods. This information is stored in the private variables of the class and obtained through set() and get(). The introspection mechanism is implemented through reflection. BeanInfo is used to expose the properties, methods and events of a bean, and then we can manipulate the properties of the JavaBean.
In Java introspection, the above classes are basically used.
You can get the methods and properties in the class through the class BeanInfo. For example, if there is an attribute name in class A, we can get its value through getname and setname or set a new value. Access the name attribute through getName/setName, which is the default rule.
Java provides a set of API to access the getter/setter method of a property. Through these APIs, you don't need to understand this rule (but you'd better find out). These APIs are stored in the package Java In beans,
The general approach is to obtain the BeanInfo information of an object through the getBeanInfo method of class Introspector, and then obtain the property descriptor through BeanInfo. Through this property descriptor, we can obtain the getter/setter method corresponding to a property, and then we can call these methods through the reflection mechanism, which is the introspection mechanism.
example
Customize a bean class:
/** * */ package beanutils; import java.util.Date; /** * JavaBean * */ public class Person { private String name;// field private String password; private int age; private Date birthday; public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getAb() { // ab is also an attribute in the bean! return null; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
Use the introspection API to manipulate the properties of the bean
/** * */ package cn.itcast.introspector; import java.beans.BeanInfo; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import org.junit.Test; /** * Use the introspection API to manipulate the properties of the bean * */ public class Demo1 { // 1. Get all the attributes of the bean @Test public void test1() throws Exception { BeanInfo info = Introspector.getBeanInfo(Person.class, Object.class);// Do not introspect properties inherited from the parent class PropertyDescriptor[] pds = info.getPropertyDescriptors();// Get property descriptor for (PropertyDescriptor pd : pds) { System.out.println(pd.getName()); } } // 2. Manipulate the specified attribute of the bean: age @Test public void test2() throws Exception { Person p = new Person(); PropertyDescriptor pd = new PropertyDescriptor("age", Person.class); // Get the writing method of the attribute and assign a value to the attribute Method method = pd.getWriteMethod(); // setAge method.invoke(p, 24); // Gets the value of the property method = pd.getReadMethod(); // getAge() System.out.println(method.invoke(p, null)); } // 3. Get the property type of the current operation @Test public void test3() throws Exception { Person p = new Person(); PropertyDescriptor pd = new PropertyDescriptor("age", Person.class); System.out.println(pd.getPropertyType()); } }
The above operations are slightly cumbersome. Apache has developed a set of API for operating JavaBeans - beautils. This API takes into account many application scenarios in actual development. Therefore, in actual development, many programmers use this set of API to operate JavaBeans to simplify the writing of program code.
Beautils Toolkit
Download address of BeanUtils Toolkit: http://commons.apache.org/beanutils/ ; Note: the package of BeanUtils depends on the logging package. The download address of the logging package is: http://commons.apache.org/logging/ .
Create a new lib directory under the project and import commons-bean utils-1.9.3 Jar and support package commons-logging-1.2 jar
Select two packages and right-click build path/add to build path
Common classes and methods of Beanutils Toolkit:
BeanUtils
PropertyUtils
ConvertUtils.regsiter(Converter convert, Class clazz)
Assign a value to a property in the bean
The following example test1() directly assigns a property in the bean through the setProperty method of the BeanUtils class.
@Test public void test1() throws IllegalAccessException, InvocationTargetException { Person p = new Person(); BeanUtils.setProperty(p, "name", "yaoer"); System.out.println(p.getName()); }
Operation results:
Custom converter
The following test2 demonstrates how to customize a converter.
Because the "1994-10-12" submitted by the user is a String, and the birthday in the bean is a Date type attribute, since the automatic conversion of String type in this set of API is limited to 8 basic types, it is impossible to convert the String to Date directly. This requires us to customize a converter.
Key: convertutils Regsiter (converter, convert, class clazz) method.
@Test public void test2() throws IllegalAccessException, InvocationTargetException { Person p = new Person(); // Simulate forms submitted by users String name = "yaoer"; String password = "123"; String age = "24"; String birthday = "1994-10-12"; // Register a date converter for beanUtils ConvertUtils.register(new Converter() { public Object convert(Class type, Object value) { if (value == null) { return null; } if (!(value instanceof String)) { throw new ConversionException("Only support String Type conversion!"); } String str = (String) value; if (str.trim().equals("")) { return null; } SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); try { return df.parse(str); } catch (ParseException e) { throw new RuntimeException(e); // Abnormal chain cannot be broken } } }, Date.class); // Encapsulate into p objects BeanUtils.setProperty(p, "name", name); BeanUtils.setProperty(p, "password", password); BeanUtils.setProperty(p, "age", age); // Automatic data conversion (basic type) BeanUtils.setProperty(p, "birthday", birthday); System.out.println(p.getName()); System.out.println(p.getPassword()); System.out.println(p.getAge()); System.out.println(p.getBirthday()); }
As shown in the figure, the conversion is successful.
One thing to note is the import package of date, import Java util. Date is correct, not sql, otherwise an error will be reported.
import java.util.Date;
Use the converter provided in the API: DateLocaleConverter
@Test public void test3() throws ConversionException, IllegalAccessException, InvocationTargetException{ Person p = new Person(); // Simulate forms submitted by users String name = "yaoer"; String password = "123"; String age = "24"; String birthday = "1994-10-12"; ConvertUtils.register(new DateLocaleConverter(), Date.class); BeanUtils.setProperty(p, "name", name); BeanUtils.setProperty(p, "password", password); BeanUtils.setProperty(p, "age", age); // Automatic data conversion (basic type) BeanUtils.setProperty(p, "birthday", birthday); System.out.println(p.getName()); System.out.println(p.getPassword()); System.out.println(p.getAge()); Date date = p.getBirthday(); System.out.println(date.toString()); }
This example reports an error, and the reason has not been found yet.
Populate the bean's properties with the values in the map collection
@Test public void test4() throws IllegalAccessException, InvocationTargetException { // TODO Auto-generated method stub Map map = new HashMap(); map.put("name","zhuzhu"); map.put("password","123"); map.put("age","24"); map.put("birthday","1994-10-12"); ConvertUtils.register(new DateLocaleConverter(), Date.class); Person bean = new Person(); BeanUtils.populate(bean, map);//Populate the bean's properties with the values in the map collection System.out.println(bean.getName()); System.out.println(bean.getPassword()); System.out.println(bean.getAge()); System.out.println(bean.getBirthday()); }
Because DateLocaleConverter is also used, the same error is reported as in the above example.
If you replace the converter with the custom converter in the test2 example, you can successfully pass the test:
summary
Introspection is based on reflection and is mainly used to operate JavaBean s. Through introspection, you can easily and dynamically obtain the set/get methods, properties and method names of bean s.
Error reporting reason: