从java反射到ORM和依赖注入实现原理

本文主要讲解反射机制的实现和反射机制在优秀框架中的使用

1.反射机制的实现:

在聊java反射之前,先看一段代码:

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

这是一个Student类,定义了一个私有name属性,一个打印方法,没有get和set方法,现在如果我想掉用Student的println方法,能否给name赋值?

为了解决这个问题,java设计了反射机制。

何为反射机制?

先看一段代码:

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();
		}
	}

上面就是一段简单的java反射实现,通过field获取Student的name属性,然后过反射访问该字段,实现给该字段赋值。

执行步骤:

1.获取field对象

2.修改field对象属性为private时可修改

3.给对象的属性赋值

通过运行main方法,能够打印张三

在了解何为反射之后,我们将这段代码进行改造:

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();
	}
}

改造之后的代码,实现了面向对象的设计,解释一下传入的三个参数:

Object obj:需要反射的具体的对象(就是告诉我给哪个学生赋值)

String field:需要实现反射的属性(就是告诉我需要给学生的赋值的是哪个属性)

Object value:需要实现反射的属性值(就是告诉我需要给学生的赋什么值)

2.ORM主要实现(基于Mybatis)

谈完反射,来谈谈ORM:

所谓ORM(对象关系映射):就是把数据库的字段变成java实体类的属性

我们看一个配置:

<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>

这个配置就是将从数据库获取的字段与实体类的字段一一对应。

具体解释一下,这段配置,有哪些信息

  • 类名
  • 类中属性名
  • 对应的数据库中数据的字段名

有了这三个信息,我就可以模拟实现了,来看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();
    }
  }

来看看怎么调用的

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;
    }

通过注入的方式实现从List<Object>到List<具体的class>,就是说,将Object通过复制,转换成我们需要的具体的实现类。

3.依赖注入的实现

何谓依赖注入?

创建被调用者 实例的工作通常由Spring容器来完成,然后注入调用者,因此也称为依赖注入。

简单来说,就是实例化对象不由开发者new去实例化,而是交给Spring 容器去实例化(详细的依赖注入的优点和缺点这里不做详细解释)。

我们来看看Spring的依赖注入怎么利用反射的。

这个是Autowired的具体实现,主要就是通过反射的方式实现。

当然,在实现注入之前,实现了判断缓存、判空等。

总结:

java的反射机制是众多优秀框架的核心实现之一,优点是,在不需要实现get和set方法的的前提下,赋值或实例化对象,降低代码之间的耦合。

猜你喜欢

转载自blog.csdn.net/qq_31205803/article/details/84891097