From java reflection to ORM and dependency injection implementation principle

This article mainly explains the implementation of reflection mechanism and the use of reflection mechanism in excellent frameworks

 

1. Implementation of reflection mechanism:

Before talking about java reflection, let's look at a piece of code:

public class Student {
	private String name;
	
	public void println(){
		System.out.println(name);
	}
}

This is a Student class, which defines a private name attribute and a printing method. There are no get and set methods. Now if I want to use Student’s println method, can I assign a value to the name?

To solve this problem, Java has designed a reflection mechanism.

What is the reflection mechanism?

First look at a piece of code:

public static void main(String[] args) {
		// TODO Auto-generated method stub
		Student stu = new Student();
		try {
			Field f = stu.getClass().getDeclaredField("name");//获取Student的name属性
			f.setAccessible(true);//允许反射使用该字段
			f.set(stu, "张三");//设置值
			stu.println();
		} catch (NoSuchFieldException | SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

 

The above is a simple java reflection implementation. The name attribute of the Student is obtained through the field, and then the field is accessed through reflection to realize the assignment of the field.

Steps:

1. Get the field object

2. Modify the field object attribute to be private

3. Assign values ​​to the properties of the object

By running the main method, you can print Zhang San

After understanding what reflection is, we transform this code:

public class Reflex {
	public static void setter(Object obj,String field,Object value){
		try {
			Field f = obj.getClass().getDeclaredField(field);
			f.setAccessible(true);
			f.set(obj, value);
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		Student stu=new Student();
		Reflex.setter(stu, "name", "张三");
		stu.println();
	}
}

The modified code implements an object-oriented design. Explain the three parameters passed in:

Object obj: the specific object that needs to be reflected (just tell me which student to assign)

String field: the attribute that needs to be reflected (that is, tell me which attribute needs to be assigned to the student)

Object value: The attribute value that needs to be reflected (that is, tell me what value I need to assign to the student)

2. ORM main implementation (based on Mybatis)

After talking about reflection, let's talk about ORM:

The so-called ORM (Object Relational Mapping): is to turn the fields of the database into attributes of java entity classes

We look at a configuration:

<resultMap id="userAndJobs1" extends="BaseResultMap" type="TUser">
		<collection property="jobs"
			ofType="com.enjoylearning.mybatis.entity.TJobHistory">
			<result column="comp_name" property="compName" jdbcType="VARCHAR" />
			<result column="years" property="years" jdbcType="INTEGER" />
			<result column="title" property="title" jdbcType="VARCHAR" />
		</collection>
	</resultMap>

This configuration is a one-to-one correspondence between the fields obtained from the database and the fields of the entity class.

Explain specifically, what information is there in this configuration

  • Class name
  • Property name in the class
  • The field name of the data in the corresponding database

With these three pieces of information, I can simulate the realization, let’s see the realization of Mybatis

 public static void copyBeanProperties(Class<?> type, Object sourceBean, Object destinationBean) {
    Class<?> parent = type;
    while (parent != null) {
      final Field[] fields = parent.getDeclaredFields();
      for(Field field : fields) {
        try {
          field.setAccessible(true);
          field.set(destinationBean, field.get(sourceBean));
        } catch (Exception e) {
          // Nothing useful to do, will only fail on final fields, which will be ignored.
        }
      }
      parent = parent.getSuperclass();
    }
  }

Let's see how to call

public static Object createProxy(Object target, ResultLoaderMap lazyLoader, Configuration configuration, ObjectFactory objectFactory, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
      final Class<?> type = target.getClass();
      EnhancedResultObjectProxyImpl callback = new EnhancedResultObjectProxyImpl(type, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);
      Object enhanced = crateProxy(type, callback, constructorArgTypes, constructorArgs);
      PropertyCopier.copyBeanProperties(type, target, enhanced);
      return enhanced;
    }

Realize from List<Object> to List<specific class> by injection, that is, copy Object into the specific implementation class we need.

3. Implementation of dependency injection

What is dependency injection?

The work of creating the callee instance is usually done by the Spring container and then injecting the caller, so it is also called dependency injection.

Simply put, the instantiated object is not instantiated by the developer new, but is handed over to the Spring container to instantiate (the advantages and disadvantages of detailed dependency injection are not explained in detail here).

Let's take a look at how Spring's dependency injection uses reflection.

This is the specific realization of Autowired, mainly through reflection.

Of course, before the injection is implemented, judgment caching, null judgment, etc. are implemented.

to sum up:

Java's reflection mechanism is one of the core implementations of many excellent frameworks. The advantage is that it can assign or instantiate objects without implementing get and set methods, reducing the coupling between codes.

Guess you like

Origin blog.csdn.net/qq_31205803/article/details/84891097