用反射和内省技术实现简单 SpringIOC

SpringIoc 实现原理 什么是SpringIOC spring ioc指的是控制反转,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。交由Spring容器统一进行管理,从而实现松耦合 “控制反转”,不是什么技术,而是一种设计思想。 在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,... 阅读详情

转自:http://blog.youkuaiyun.com/newjueqi/archive/2009/06/03/4238602.aspx

【文章标题】用反射和内省技术实现简单 SpringIOC

【文章作者】曾健生

【作者邮箱】 zengjiansheng1@126.com

【作者 QQ 】 190678908

【作者博客】 http://blog.youkuaiyun.com/newjueqi

【作者声明】欢迎转载文章,但转载请保留文章的完整性以及注明文章的出处。

 

*******************************************************************************

       我们知道, spring 是个开源的控制反转( Inversion of  Control , IoC )和面向切片( AOP )的容器框架。所谓控制反转就是应用本身不负责依赖对象的创建和维护,依赖对象的创建及维护是由外部容器负责的。这样控制权就由应用转移到外部容器,控制权的转移就是所谓的反转。

       我们把需要创建的对象信息写在一个 XML 文件中,每次需要维护对象时只需要修改 XML 文件中的配置信息,不需要重新更改和编译代码,为项目开发带来了极大的方便。

 

反射

       在以前的文章《 JDK5.0 新特性( 2 )——反射》 ( http://blog.youkuaiyun.com/newjueqi , http://newjueqi.javaeye.com/) 中就已经介绍过反射技术,有了反射技术,就能方便地根据 XML 的配置创建对象。那对象的维护应该怎么实现呢?这就需要内省技术出马了 ^-^

 

内省

       内省是 Java 中 Bean 类属性的一种缺省的处理方式。例如,有一个类 Person ,其中有个 age 属性,可通过 setAge ()和 getAge ()方法获取 / 设置 age 的值。通过 setAge() /getAge ()获取 / 设置 age 的值是 Java 中的默认的处理规则, Java 提供了一套 API 来访问某个属性的 setAge () /getAge ()。

通用的用法通过类 Introspector 来获取某个对象的 BeanInfo 信息,然后通过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后通过反射机制来调用这些方法

      

 

实现简单 SpringIOC

       通过反射技术,就能动态地创建对象;通过内省技术,就能方便地维护对象。通过以上的两个技术基础,就能实现简单的 SpringIOC 。

 

譬如, XML 文件中有如下的配置信息

    < bean id = "personDAO" class = "org.petrelsky5.dao.impl.PersonDAOImpl" />

   

    < bean id = "personService" class = "org.petrelsky5.service.impl.PersonServiceImpl" >

       < property name = "personDAO" ref = "personDAO" />

       < property name = "name" value = "Tom12345" ></ property >

       < property name = "age" value = "12" ></ property >

    </ bean >

 

 

其中 SpringTest.java 文件中 instanceSpring() 有如下测试代码:

 

ClassPathXmlApplicationContext ctx = null ;

       ctx = new ClassPathXmlApplicationContext( "beans.xml" );

 

       PersonDAO personService = (PersonDAO) ctx

              .getBean( "personDAO" );

       personService.add();

 

其中的调用关系如下图 1 :

 

                                                        图 1

 

在 SpringTest.java 文件中 instanceSpring2() 有如下测试代码:

 

       ClassPathXmlApplicationContext ctx = null ;

       ctx = new ClassPathXmlApplicationContext( "beans.xml" );

 

       PersonService personService = (PersonService) ctx

              .getBean( "personService" );

       personService.save();

 

其中的调用关系如下图 2 :

 

                                                        图 2

 

由此可知道:

(1)        类 ClassPathXmlApplicationContext 相当于一个容器。

(2)        在 XML 文件的节点 bean 中,各部分的内容解释如下:

A.  id :类的标识。

B. class :类的所在路径。

C. property :属性信息

①      name :属性名称。

②      value: 如果属性是值类型的,那么 value 是相应的属性值。

③      ref :如果属性是引用类型(譬如 PersonServiceImpl 类中的属性 personDAO ,指向类 PersonDAO ),那么 ref 是所指向的对象。

 

 

我们根据在 XML 文件信息和 类 ClassPathXmlApplicationContext 的功能,讨论一下相关的数据怎么存储(即数据结构)。

( 1 )在 类 ClassPathXmlApplicationContext 中有个方法 getBean ,可根据 id 值获取一个实际的对象,即 id 和对象是一一对应的关系,所以定义一个 Map 集合:

    Map<String,Object>

其中, 键为 id, 值 Object 为对应的对象。

 

( 2 ) 虽然现在编写的 XMl 文件中只有两个 Bean 节点,但我们都必须用面向对象的思想把 Bean 节点对象化,每个 bean 有以下三个属性:

1.    id

2.    class

3.    bean 节点(数量不确定)

 

由于 bean 节点的数量是不确定,对于数量不确定的数据的存储,自然地想到了用集合。

而每个 bean 又有三个属性:

1.    name :属性名称

2.    value :属性的数据值(可能有)

3.    ref :属性所指向的引用值(可能有)

 

所有的数据结构关系如图 3 所示:

 

                           图 3

 

 

    现在数据的相互关系已经清楚了,接下来就是程序的流程。

    我们在类 ClassPathXmlApplicationContext 初始化时只传入了 XML 文件的名称,以后只是在有需要时用 getBean ()获取 id 制定的对象,所以应该在类初始化时就把所有的对象创建完毕。

    根据如上的描述,可以把初始化分为以下三步:

1.    把 XML 的信息保存到相关的类中

2.    初始化每个 Bean , 把 id 值和 class 对应的对象保存在 Map 集合中

3.    设置 XMl 文件中每个 Bean 指定的值

 

这三步的代码如下:

1. 把 XML 的信息保存到相关的类中

// 把 XML 的信息保存到相关的类中

    public void initXML( String fileName )

    {

       URL url= null ;

       Document doc= null ;

      

       // 获取 XML 文件的 url

       url= this .getClass().getClassLoader().getResource( fileName );

       SAXReader saxreader= new SAXReader();

      

       try {

           // 获取 XML 的文档对象

           doc=saxreader.read( url);

       } catch (DocumentException e) {

           // TODO Auto-generated catch block

           e.printStackTrace();

           return ;

        }

      

       // 获取根节点

       List<Element> beans=doc.getRootElement().elements( "bean" ) ;

      

       // 遍历所有的 Bean 节点,把 class , id , property 保存起来

       for ( Element ele: beans )

       {

           // 创建一个 BeanInfo 对象

           BeanInfomation beanInfo= null ;

           beanInfo= new BeanInfomation( ele.attributeValue( "class" ),

                               ele.attributeValue( "id" ) );

          

           // 获取一个 Bean 中的所有 property

           List<Element> properties=ele.elements( "property" ) ;

          

           // 遍历所有的 property 信息

           for ( Element pro: properties )

           {

              Property property= null ;

             

              // 把 property 信息保存

              property= new Property(  pro.attributeValue( "name" ),

                                   pro.attributeValue( "value" ),

                                   pro.attributeValue( "ref" ) );

             

              beanInfo.addProperty( property );

           }

             

           beanList .add( beanInfo );         

       }

    }

 

2. 初始化每个 Bean ,把 id 值和 class 对应的对象保存在 Map 集合中

 

public void initBean ()

    {

       for ( BeanInfomation beaninfo: beanList )

       {

           String id=beaninfo.getId();

           String className=beaninfo.getClassName();

           Object obj= null ;

          

           try {

              // 用反射获取一个类的对象

              obj=Class.forName ( className ).newInstance();

           } catch ( Exception e) {

              // TODO Auto-generated catch block

              e.printStackTrace();

           }

          

           // 把 id 值和 class 对应的对象保存在 Map 集合中

           objectMap .put( id, obj );

       }

    }

 

3. 设置 XMl 文件中每个 Bean 指定的值

    public void initBeanProperty()

    {

       List<BeanInfomation> beanList=getBeanList();

      

       List<Property> proList= null ;

      

       // 遍历每个 Bean 类,读取其中的信息

       for ( BeanInfomation beaninfo: beanList)

       {

           String id=beaninfo.getId();

          

           // 根据 ID 值从 Map 集合中获取对象

           Object obj= objectMap .get(id);

          

           BeanInfo beanInfos= null ;

          

           // 获取 bean 中的属性值集合

           proList=beaninfo.getPerprotyList();

          

           for ( Property pro: proList )

           {

              String name=pro.getName();

              String ref=pro.getRef();

              Object value= null ;

             

              // 判断 ref 是否为空

              if ( ref!= null )

              {

                  value= objectMap .get( ref );

                 

              }

              else

              {

                  value=pro.getValue();

              }

             

              Class clazz=obj.getClass();

             

              try {

                  beanInfos = Introspector.getBeanInfo (clazz);

              } catch (IntrospectionException e1) {

                  // TODO Auto-generated catch block

                  e1.printStackTrace();

              }

              PropertyDescriptor[] propertyDescriptes=

                  beanInfos.getPropertyDescriptors();

             

              for ( PropertyDescriptor propertyDescript:propertyDescriptes )

              {

                  if ( name!= null && name.equals( propertyDescript.getName()))

                  {

                     try {

                         // 设置指定属性的值

                         propertyDescript.getWriteMethod().invoke( obj,value );

                     } catch (Exception e) {

                         // TODO Auto-generated catch block

                         e.printStackTrace();

                     }

                     break ;

                  }

              }

             

           }

       }

    }

 

 

最后就是完成 getBean 函数

 

// 获取对象

    public Object getBean( String beanName )

    {

       Object obj= null ;

       obj= objectMap .get(beanName);

       return obj;

    }

 

测试:

 

1.     运行测试代码:

public void instanceSpring() {

       ClassPathXmlApplicationContext ctx = null ;

       ctx = new ClassPathXmlApplicationContext( "beans.xml" );

 

       PersonDAO personService = (PersonDAO) ctx

              .getBean( "personDAO" );

       personService.add();

 

    }

 

输出结果如图 4 :

 

                            图 4

 

2.    运行测试代码:

public void instanceSpring2() {

       ClassPathXmlApplicationContext ctx = null ;

       ctx = new ClassPathXmlApplicationContext( "beans.xml" );

 

       PersonService personService = (PersonService) ctx

              .getBean( "personService" );

       personService.save();

    }

运行结果如图 5 :

 

              图 5

 

3.    运行测试代码:

public void instanceSpring3(){

       ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext( "beans.xml" );

       PersonServiceImpl ps = (PersonServiceImpl) ctx.getBean( "personService" );

      

       ps.save();

       String name = ps.getName();

       System. out .println( "name: " + name);

       System. out .println( "age: " + ps.getAge());

    }

运行结果如图 6 :

 

 

                  图 6

 

    ^-^ 结果证明代码编写正确!!!

 

源码下载地址:https://docs.google.com/leaf?id=0B3cFfe7PkmkxYzUwMGNkYzItMTUwNS00ZTAyLTg1YTctZmIxZGViZTgwZWJm&sort=name&layout=list&num=50

手动实现的简单Spring框架 使用java纯手动实现的一个简单的Spring框架,pom.xml文件中只包含一个Servlet依赖jar包,参考的网上视频教学做的,仅用于学习 立即下载

相关推荐

Spring框架的简单实现

我们从一个简单的容器开始,一步步的重构,最后实现一个基本的Spring框架的雏形,为了帮助我们更加深入的理解Spring的IoC的原理和源码。 详细内容见博文: 【SSH进阶之路】一步步重构容器实现Spring框架——从一个简单的容器开始(八) 【SSH进阶之路】一步步重构容器实现Spring框架——解决容器对组件的“侵入式”管理的两种方案--服务定位器和IoC容器(九) 【SSH进阶之路】一步步重构容器实现Spring框架——配置文件+反射实现IoC容器(十) 【SSH进阶之路】一步步重构容器实现Spring框架——彻底封装,实现简单灵活的Spring框架(十一)

用反射和内省技术实现简单SpringIOC

【文章标题】用反射和内省技术实现简单SpringIOC【文章作者】曾健生【作者邮箱】zengjiansheng1@126.com【作者QQ】190678908【作者博客】http://blog.youkuaiyun.com/newjueqi【作者声明】欢迎转载文章,但转载请保留文章的完整性以及注

曾健生的专栏 2537

模拟Spring的简单实现

本文的主要内容就是学习Spring的开端,模拟一下Spring的实现,感兴趣的小伙伴可以参考一下

(Spring学习02)简单实现spring方式了解底层主要原理

简单实现spring方式了解底层主要原理

a250029634的博客 118

将机器人urdf模型转换为Mujoco环境下的mjcf模型

在使用gym环境进行人形模型站立训练的过程中,我想要将之前ros环境下的机器人urdf模型导入到mujoco环境下,这时候就需要将urdf模型转换为mujoco专用的mjcf模型。-AzureLoong.urdf是机器人模型(我这里使用青龙的模型);--custom_robot.xml是转换完成之后的机器人模型的名字和格式;包要求 Python 版本必须是 3.11 或更高),保证自己的其他训练环境和依赖不被干扰。首先将meshes文件迁移到需要输出的目录下,然后再运行转换命令。最后就可以成功输出了。

weixin_44334573的博客 3756

西门子S7-200 SMART控制步进电机(二)

目录 一、开环运动控制方法 二、运动轴概述 三、配置运动控制向导 一、开环运动控制方法 S7-200 SMART CPU提供三种开环运动控制的方法: 1、脉冲宽度调制(PWM):内置于CPU中,用于速度、位置或占空比的控制 2、脉冲串输出(PTO):内置于CPU中,用于指定长度脉冲或指定距离的控制 3、运动轴:内置于CPU总,用于速度和位置的控制。本文所讲的就是通过运动轴实现步进电机的运动控制。 SR20和ST20 CP...

qq_43134642的博客 2万+

反射与工厂模式实现Spring IOC

反射机制概念 我们考虑一个场景,如果我们在程序运行时,一个对象想要检视自己所拥有的成员属性,该如何操作?再考虑另一个场景,如果我们想要在运行期获得某个类的Class信息如它的属性、构造方法、一般方法后再考虑是否创建它的对象,这种情况该怎么办呢?这就需要用到反射! 我们.java文件在编译后会变成.class文件,这就像是个镜面,本身是.java,在镜中是.class,他们其实是一样的;那么同理,我们看到镜子的反射是.class,就能通过反编译,了解到.java文件的本来面目。 对于反射,官方给出的概念:反射

weixin_45038271的博客 580

DBeaver连接ClickHouse保姆级教程:从安装到成功测试(附驱动下载问题解决)

本文提供了一份详细的DBeaver连接ClickHouse实战指南,重点解决了驱动下载失败等常见问题。文章从环境准备、DBeaver安装讲起,详细阐述了手动配置ClickHouse驱动的可靠方案,并逐步指导完成连接配置与测试,最后介绍了基础操作与查询优化技巧,旨在帮助用户高效完成连接并快速上手使用。

pink的博客 879

spring 源码阅读(基础)-第二章 基础工具

1.什么是内省:内省是java语言针对bean属性,事件的一种缺省处理方法,spring源码中也经常会出现相关的api。javaBean是一种特殊的类,主要用于信息传递,这种类中的方法主要用于私有字段的访问,且方法名符合某种命名规则,事实上,内省机制也是通过反射来实现的。反射的功能是比内省强大的。在Java内省中,用到的基本上就是上述几个类。内省api的一般的做法是通过类 Introspector 的 getBeanInfo方法来获取某个对象的。

weixin_41636858的博客 325

远程声控系统(MATLAB代码见优快云资源)

远程声控系统技术报告 一、题目要求 实现一个远程声音控制系统。首先采集不同的语音指示信号,进行适当压缩;然后通过噪声信道实现远程传输,远端接收后再通过适当计算识别出是何指示,最后送入一个处于未知状态、但能控/能观的控制系统,完成不同的控制动作。 二、问题分解与解决思路 2.1 系统设计 实验中以汉语数字语音1~9作为指令,数字语音“1”代表一号指令,数字语音“2”代表二号指令,依次类推。发送端发出语音“1”,发送端对应的数字语音文件为“1b.wav”,通过信源编码对语音进行压缩编码,然后进行信道编码并进行基

业精于勤,荒于嬉 5734

内网渗透(二)之基础知识-工作组介绍

在一个大型单位里,可能有成百上千台计算机互相连接组成局域网,它们都会列在"网络"(网上邻居)内。如果不对这些计算机进行分组,网络的混乱程度是可想而知的 为了解决这一问题,产生了工作组( Work Group)这个概念。将不同的计算机按功能(或部 门)分别列入不同的工作组,例如技术部的计算机都列入"技术部"工作组、行政部的计算机都 列入"行政部"工作组。要想访问某个部门的资源,只要在"网络"里双击该部门的工作组名 就可以看到该部门的所有计算机了。相比不分组的情况,这样的情况有序得多(尤其对大型局域网来说)。

把自己活成一道光,因为你不知道,谁会借着你的光,走出了黑暗。请保持心中的善良,因为你不知道,谁会借着你的善良,走出了绝望。请保持你心中的信仰,因为你不知道,谁会借着你的信仰,走出了迷茫。请相信自己的力量,因为你不知道,谁会因为相信你,开始相信了自己.... 1219

Spring框架之内省

JavaBean规范: 1)JavaBean类必须是一个public的类; 2)JavaBean类必须是有一个空的构造函数; 3)JavaBean的变量应为private; 4)JavaBean的属性通过getter/setter访问; 反射与内省 1)反射可以操作各种类属性,设置属性值可不用调用setter方法; 2)内省是Java提供的一套API,...

jiabaoyu19lindaiyu的博客 1068

C/C++跳动的爱心(完整代码)

C语言实现跳动的爱心的完整代码。

AIGC 5842

原来手写SpringIOC如此简单

相信所有学过Java的人都应该学习并使用过Spring框架,它是最受欢迎的企业级Java应用程序开发框架,数以千万的来自世界各地的开发人员都在使用 Spring 框架进行程序开发。而Spring的核心是IOC(控制反转)和AOP(面向切面编程)。下面我将会对SpringIOC做详细的介绍并使用反射技术手写一个SpringIOC。 1.什么是SpringIOC? 所谓IOC(控制反转),对于Spring框架来说,就是由Spring来负责控制对象的生命周期和对象之间的关系。在传统的程序开发中,如果在一个对象中要

Mr_wxc的博客 4232

【git】git: ‘interpret-trailers’ is not a git command. See ‘git --help’

cents 7.6系统. yum源安装git最新版本是1.8.3 报错: git: 'interpret-trailers' is not a git command. See 'git --help'. cannot insert change-id line in .git/COMMIT_EDITMSG 解决: git add xxx git commit -m "xxx" 然后修改 vim .git/hooks/commit-msg #if test -n "${reviewurl}" ; th

machh的专栏 4758

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

java反射和注解实现简单的springIOC

我们都知道光是可以反射的,我们无法直接接触方法区中一个类的方法、属性、注解等,那就可以通过一面镜子观察它的全貌,这个镜子就是JDK给我们提供的Class类。​ getFields只能获取被public修饰的成员变量,当然反射很牛,我们依然可以使用getDeclaredFields方法获取所有的成员变量。注解的类 在内存中只会有一份 实现了单例设计模式 我们可以通过在类上加注解的方式对 类进行单例!​ 在java中万物皆对象成员变量也是对象,他拥有操作一个对象的成员变量的能力。

QUIT_0110的博客 344

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

利用反射手写有一个简单的SpringIOC框架

SpringIOC SpringIOC就是将创建对象的控制权交给Spring容器来进行管理。容器就是XML文件 实现思路: 1、使用dom4j来读取XML文件,获取document对象 2、通过id来获取到配置文件中class里面的值,使用反射技术进行实例化 3、property属性里面的name和value,我们可以使用反射给这些属性进行赋值 配置文件 &lt;?xml version="1.0...

qq_37630321的博客 271

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Java反射技术--SpringIOC原理和SpringAop原理

文章目录Java的反射实现极简IOC容器(SpringIOC原理)SpringAop原理 前言 相信很多人都知道反射可以说是Java中最强大的技术了,它可以做的事情太多太多,很多优秀的开源框架都是通过反射完成的,比如最初的很多注解框架,后来因为java反射影响性能,所以被运行时注解APT替代了,java反射有个开源框架jOOR相信很多人都用过,不过我们还是要学习反射的基础语法,这样才能自己写出优秀的框架,当然这里所讲的反射技术,是学习Android插件化技术、Hook技术等必不可少的! Java的反射 动态

whdyg的博客 464

简单学习下springIoc以及利用反射机制是如何实现的

文章目录什么是springIoc手写springIoc实现思路 什么是springIoc IOC(Inversion of Control) 意为控制反转,他是一种设计思想.并非实际的技术.最核心的思想就是将对象实例创建的控制权交给程序(IOC 容器) IOC 容器: 一个管理所有控制反转过程中创建的对象的 key-value 容器结构(可以简单理解为:hashMap) Spring 的 IOC(...

凹凸曼的博客 1754

SpringIOC(手写简单实现)

目录 概念 手写SpringIOC XML版本 手写SpringIOC 注解版本 概念 spring ioc指的是控制反转,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。交由Spring来管理这些,实现解耦。 简单来说就是把每个bean与bean之间的关系交给了第三方容器进行管理,关于bean的初始化交给了Spring容器 传统应用程序 IOC容器 ...

5lovetutu的专栏 1025

实现一个简单的SpringIOC容器

主要思想: 提到IOC,第一反应就是控制反转,我以前以为SpringIOC就是控制反转,控制反转就是SpringIOC,当然这种理解是错误的,控制反转是一种思想,一种模式,而Spring的IOC容器是实现了这种思想这种模式的一个载体. 使用过Spring的人都熟知,SpringIOC容器可以在对象生成或初始化时就直接将数据注入到对象中,如果对象A的属性是另一个对象B,还可以将这个对象B的引用注...

赵树祥的博客 849

Java反射机制--手写springioc

什么是Java反射 正在运行,动态获取这个类的所有信息 反射机制的作用 1,反编译:.class–>.java 2.通过反射机制访问java对象的属性,方法,构造方法等; 反射机制的应用场景 Jdbc 加载驱动----- Spring ioc 框架 反射创建api 方法名称 作用 getDeclaredMethods [] 获取该类的所有方法 getReturnType() 获取该类的返回值...

HMing的博客 353

SpringIOC的模拟实现

容器的初始化、Bean 实例的创建与依赖注入,以及最终调用。方法,对指定目录下的所有文件进行递归扫描,将文件路径存于。// 我们所持有的所有对象 在beans中。综上所述,整个程序的运行调用流程涵盖了。// 从beans 中获得对应的对象。//field 需要由我们来赋值。3. 获取Bean实例并调用方法。方法,设定基础路径和基础包名。注解标记的类的实例,将其存储在。// 根据当前域中的类型的名字。注解标记的字段进行依赖注入。列表,运用反射机制创建被。方法来执行具体业务逻辑。

m0_73971785的博客 950
上一篇: java的内省机制
下一篇: spring中的设计模式
FG2006
博客等级 码龄19年 395粉丝 66原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值