Spring IOC中java反射技术的深入了解

4 篇文章 0 订阅

 

再说Spring IOC(控制反转)之前我们先简单说一下java的反射技术,对他了解了那么对于理解spring的底层实现就容易多了

Spring 的底层是 Dom4j+java 反射机制 ,Dom4j解析XML,反射机制主要是实例化bean.

 

 

 

一:先说一下反射技术创建类的三种方式

//第一种方法:forName      Class<?> class1 = Class.forName("com.app.Person");      Objectclass1 =cls.newInstance(); 

//第二张方法:class        Class<?> class2 = Person.class;          

//第三种方法:getClass        Person person = new Person();          Class<?> class3 = person.getClass();

 

面试时我们经常会问到这样一个问题:

问:new和newInstance关键字之间的区别

    答:(1)在执行Class.forName("a.class.Name")时,JVM会在classapth中去找对应的类并加载,这时JVM会执行该类的静态代码段。在使用newInstance()方法的时候,必须保证这个类已经加载并且已经连接了,而这可以通过Class的静态方法forName()来完成的。   
    使用关键字new创建一个类的时候,这个类可以没有被加载,一般也不需要该类在classpath中设定,但可能需要通过classlaoder来加载。

 (2)new关键字能调用任何构造方法。
 newInstance()只能调用无参构造方法。

如果你能答出来,那么恭喜你,由这个问题又衍生出两个问题

 

1.既然使用newInstance()构造对象的地方通过new关键字也可以创建对象,为什么又会使用newInstance()来创建对象呢?

答:主要提高可伸缩性、可扩展性,看下面这句代码,如果需要修改的话,那个更容易些呢?

Door door = (Door) Class.forName(className).newInstance();

Door door = new AutoDoor() ;

 

2.ClassLoader.loadClass和Class.forName的区别?

答:Class.forName得到的class是已经初始化完成的,也就是说已经执行类变量赋值和静态代码块.
Classloder.loaderClass得到的class是还没有链接的,也就是没有执行类变量和静态代码块.

 

别说我问题多,解决一个问题,可以帮助我们检查相关的知识,达到知其然和其所以然,只有这样时间长了,我们才能达到触类旁通.

 

 

二:控制反转和依赖注入是从不同方面讲的同一个东西

OC:即“控制反转”,不是什么技术,而是一种思想。使用IOC意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。

DI:依赖注入,解决对象之间的依赖关系。

本篇文章主要讲解一下IOC底层实现的原理(反射),Bean容器的实现,就不对IOC的概念进行详述了。

在Spring的配置文件中,经常看到如下配置:

 

[html] view plain copy

  1. <bean id="courseDao" class="com.qcjy.learning.Dao.impl.CourseDaoImpl"></bean>  


那么通过这样配置,Spring是怎么帮我们实例化对象,并且放到容器中去了了?对,就是通过反射!!!

 

下面是Spring通过配置进行实例化对象,并放到容器中的伪代码:

 

[html] view plain copy

  1. //解析<bean .../>元素的id属性得到该字符串值为“courseDao”  
  2. String idStr = "courseDao";  
  3. //解析<bean .../>元素的class属性得到该字符串值为“com.qcjy.learning.Dao.impl.CourseDaoImpl”  
  4. String classStr = "com.qcjy.learning.Dao.impl.CourseDaoImpl";  
  5. //利用反射知识,通过classStr获取Class类对象  
  6. Class<?> cls = Class.forName(classStr);  
  7. //实例化对象  
  8. Object obj = cls.newInstance();  
  9. //container表示Spring容器  
  10. container.put(idStr, obj);  

通过解析xml文件,获取到id属性和class属性里面的内容,利用反射原理获取到配置里面类的实例对象,存入到Spring的bean容器中。

 

 

当一个类里面需要应用另一类的对象时,Spring的配置如下所示:

 

[html] view plain copy

  1. <bean id="courseService" class="com.qcjy.learning.service.impl.CourseServiceImpl">  
  2.      <!-- 控制调用setCourseDao()方法,将容器中的courseDao bean作为传入参数 -->  
  3.      <property name="courseDao" ref="courseDao"></property>  
  4. </bean>  

我们继续用伪代码的形式来模拟实现一下Spring底层处理原理:

 

 

[java] view plain copy

  1. //解析<property .../>元素的name属性得到该字符串值为“courseDao”  
  2. String nameStr = "courseDao";  
  3. //解析<property .../>元素的ref属性得到该字符串值为“courseDao”  
  4. String refStr = "courseDao";  
  5. //生成将要调用setter方法名  
  6. String setterName = "set" + nameStr.substring(01).toUpperCase()  
  7.         + nameStr.substring(1);  
  8. //获取spring容器中名为refStr的Bean,该Bean将会作为传入参数  
  9. Object paramBean = container.get(refStr);  
  10. //获取setter方法的Method类,此处的cls是刚才反射代码得到的Class对象  
  11. Method setter = cls.getMethod(setterName, paramBean.getClass());  
  12. //调用invoke()方法,此处的obj是刚才反射代码得到的Object对象  
  13. setter.invoke(obj, paramBean);  

 

通过上面对Spring底层原理的分析,可以发现,其实并不难,用到的都是反射机制,通过反射实例化对象,存入到Spring的bean容器中。

 

第二部分内容属于转载: http://blog.csdn.net/mlc1218559742/article/details/52774805

 

最后一个问题:

问:spring ioc的优缺点?
答:优点:反射一般在框架中使用较多。因为框架要适用更多的情况。对灵活性要求较高。
缺点:运用反射会使我们的软件的性能降低,复杂度增加,所以还要我们慎重的使用它。

 

只要在代码或配置文件中看到类的完整路径(包.类),其底层原理基本上使用的就是Java的反射机制。

稍微拓展一下,Spring的Aop的底层原理是用到设计模式,动态代理模式.

动态代理又分为jdk动态代理和cglib代理,源码里面会有一个判断,如果被代理对象实现了接口,那么默认使用JDK动态代理,如果代理对象没有实现任何接口,那么就默认使用CGlib动态代理。

IOC的基本流程!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值