`
chenzehe
  • 浏览: 538244 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

模拟Spring属性的注入

 
阅读更多

1、 创建场景代码,配置spring 属性注入

新建包dao ,创建接口 IPersonDao

/**

 * Huisou.com Inc.

 * Copyright (c) 2011-2012 All Rights Reserved.

 */

package com.chenzehe.spring.dao;

/**

 * @description

 * 

 * @author chenzehe

 * @email hljuczh@163.com

 * @create 2012-4-17 下午08:56:39

 */

public interface IPersonDao {

    void save();

}
 

创建IPersonDao 的实现类:

/**

 * Huisou.com Inc.

 * Copyright (c) 2011-2012 All Rights Reserved.

 */

package com.chenzehe.spring.dao.impl;

import com.chenzehe.spring.dao.IPersonDao;

/**

 * @description

 * 

 * @author chenzehe

 * @email hljuczh@163.com

 * @create 2012-4-17 下午08:57:33

 */

public class PersonDao implements IPersonDao {

    public void save() {

        System.out.println("PersonDao save()...");

    }

}
 

创建 Service包,新建接口 IHelloWorld

package com.chenzehe.spring.service;

public interface IHelloWorld {

    void sayHelloWorld();

    void save();

}
 

创建新接口的实现类Helloworld ,该类中有属性 IPerson 类型:

package com.chenzehe.spring.service.impl;

import com.chenzehe.spring.dao.IPersonDao;

import com.chenzehe.spring.service.IHelloWorld;

public class HelloWorldImpl implements IHelloWorld {

    private IPersonDao personDao;

    public void save() {

        personDao.save();

    }

    public HelloWorldImpl() {

        System.out.println("实例化!");

    }

    public void sayHelloWorld() {

        System.out.println("Hello World!");

    }

    public IPersonDao getPersonDao() {

        return this.personDao;

    }

    public void setPersonDao(IPersonDao personDao) {

        this.personDao = personDao;

    }

}
 

spring 配置文件 applicationContext.xml 中配置 benan

 

<bean id="personDao" class="com.chenzehe.spring.dao.impl.PersonDao" />

<bean id="helloWorld" class="com.chenzehe.spring.service.impl.HelloWorldImpl">

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

</bean>
 

创建单元测试类HelloWorldTest

 

package com.chenzehe.spring.test.junit;

import org.junit.Test;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.chenzehe.spring.service.IHelloWorld;

public class HelloWorldTest {

    @Test
    public void instanceApplicationContext() {

        ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");

        IHelloWorld helloWorld = (IHelloWorld) cxt.getBean("helloWorld");

        helloWorld.sayHelloWorld();

        helloWorld.save();

    }

}
 

2、定义 Bean 属性描述类 PropertyDefinition

/**

 * Huisou.com Inc.

 * Copyright (c) 2011-2012 All Rights Reserved.

 */

package com.chenzehe.spring.myspring;

/**

 * @description

 * 

 * @author chenzehe

 * @email hljuczh@163.com

 * @create 2012-4-17 下午08:39:22

 */

public class PropertyDefinition {

    private String name;

    private String ref;

    public PropertyDefinition() {
 
    }

    public PropertyDefinition(String name, String ref) {

        this.name = name;

        this.ref = ref;

    }

    public String getName() {

        return this.name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public String getRef() {

        return this.ref;

    }

    public void setRef(String ref) {

        this.ref = ref;

    }

}
 

3 把该属性描述对象添加到 Bean 对象描述定义类 BeanDefinition 中,一个 Bean 可以有多个属性,所以对象属性为集合类型。

package com.chenzehe.spring.myspring;

import java.util.ArrayList;

import java.util.List;

public class BeanDefinition {

    private String id;

    private String className;

    private List<PropertyDefinition> propertys = new ArrayList<PropertyDefinition>();

    public BeanDefinition() {

    }

    public BeanDefinition(String id, String classPath) {

    this.id = id;

    this.className = classPath;

    }

    public String getId() {

        return id;

    }

    public void setId(String id) {

        this.id = id;

    }

    public String getClassName() {

        return className;

    }

    public void setClassName(String className) {

        this.className = className;

    }

    public List<PropertyDefinition> getPropertys() {

        return this.propertys;

    }

    public void setPropertys(List<PropertyDefinition> propertys) {

        this.propertys = propertys;

    }

}
 

4、 在原先代码 模拟spring 生成 bean 基础上增加注入功能

在解析xml 文件生成 bean 描述对象时解析描述描述对象,并添加到 bean 对象的 properys 属性中。然后再添加注入方法 injectObject()


package  com.chenzehe.spring.myspring;

import  java.beans.Introspector;

import  java.beans.PropertyDescriptor;

import  java.io.File;

import  java.lang.reflect.Method;

import  java.util.ArrayList;

import  java.util.HashMap;

import  java.util.List;

import  java.util.Map;

import  org.apache.commons.lang.StringUtils;

import  org.jsoup.Jsoup;

import  org.jsoup.nodes.Document;

import  org.jsoup.nodes.Element;

import  org.jsoup.select.Elements;

public   class  ClassPathXmlApplicationContext  {

    // 保存从配置文件中解析出来的bean属性

    private  List<BeanDefinition> beans =  new  ArrayList<BeanDefinition> () ;

    // 保存实例化好的bean

    private  Map<String, Object> beansClass =  new  HashMap<String, Object> () ;

    /**

     * 根据Bean名称取得Bean实例

    */

    public  Object getBean ( String name )   {

        return   beansClass .get ( name ) ;

    }

    /**

     * 传入配置文件初始化

     */

    public  ClassPathXmlApplicationContext ( String xmlFilePath )   {

        initBeansFromXML ( xmlFilePath ) ;

        initBeansClass () ;

        injectObject () ;

    }

    /**

     * 为Bean对象的属性注入值

     */

    private   void  injectObject ()   {

        // 循环所有bean

        for   ( BeanDefinition beanDefinition :  beans )   {

            Object bean =  beansClass .get ( beanDefinition.getId ()) ;

                if   ( bean !=  null )   {

        try   {

            PropertyDescriptor []  ps = Introspector. getBeanInfo ( bean.getClass ()) .getPropertyDescriptors () ;

           for   ( PropertyDefinition propertyDefinition : beanDefinition.getPropertys ())   {

            for   ( PropertyDescriptor propertyDescriptor : ps )   {

            if   ( propertyDefinition.getName () .equals (  propertyDescriptor.getName ()))   {

        Method setterMethod = propertyDescriptor.getWriteMethod () ; // 获取setter方法

        if   ( setterMethod !=  null )   {

            setterMethod.setAccessible ( true ) ;

            Object value =  beansClass .get ( propertyDefinition.getRef ()) ;

            setterMethod.invoke ( bean, value ) ; // 把引用对象注入到属性中

        }

        break ;

    }

}

}

}

catch   ( Exception e )   {

//  TODO : handle exception

}

}

}

}

/**

 * 从beans中读取Bean属性,使用反射实例化Bean对象

 */

private   void  initBeansClass ()   {

for   ( BeanDefinition bean :  beans )   {

if   ( StringUtils. isNotBlank ( bean.getClassName ()))   {

try   {

beansClass .put ( bean.getId () , Class. forName ( bean.getClassName ()) .newInstance ()) ;

}

catch   ( Exception e )   {

e.printStackTrace () ;

}

}

}

}

/**

 * 使用 Jsoup 解析配置文件,把bean属性存到beans

 */

private   void  initBeansFromXML ( String xmlFilePath )   {

try   {

Document  doc  = Jsoup. parse ( new  File ( xmlFilePath ) ,  "UTF-8" ) ;

Elements beanElements =  doc .getElementsByTag ( "bean" ) ;

for   ( Element element : beanElements )   {

String id = element.attr ( "id" ) ;

String classPath = element.attr ( "class" ) ;

BeanDefinition bean =  new  BeanDefinition ( id, classPath ) ;

// 取得所有属性元素

Elements propertyElements = element.getElementsByTag ( "property" ) ;

for   ( Element propertyElement : propertyElements )   {

String propertyName = propertyElement.attr ( "name" ) ;

String propertyRef = propertyElement.attr ( "ref" ) ;

PropertyDefinition propertyDefinition =  new  PropertyDefinition ( propertyName, propertyRef ) ;

// 把属性元素定义添加到bean定义中

bean.getPropertys () .add ( propertyDefinition ) ;

}

beans .add ( bean ) ;

}

}

catch   ( Exception e )   {

e.printStackTrace () ;

}

}

} 
 

 

在单元测试中使用该注入器:


package com.chenzehe.spring.test.junit;

import org.junit.Test;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.chenzehe.spring.service.IHelloWorld;

public class HelloWorldTest {

    @Test

    public void instanceApplicationContext() {

        ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");

        IHelloWorld helloWorld = (IHelloWorld) cxt.getBean("helloWorld");

        helloWorld.sayHelloWorld();

        helloWorld.save();

        com.chenzehe.spring.myspring.ClassPathXmlApplicationContext mycxt = new com.chenzehe.spring.myspring.ClassPathXmlApplicationContext(

"E:\\chenzehe\\study\\Spring\\eclipse\\workspace\\com.chenzehe.spring\\src\\main\\resources\\applicationContext.xml");

        IHelloWorld myHelloWorld = (IHelloWorld) mycxt.getBean("helloWorld");

        myHelloWorld.sayHelloWorld();

        myHelloWorld.save();

    }

} 
 

 

5、 内部Bean 注入

以上模拟注入对于内部Bean 的注入依然生效,即 Bean 的配置文件改成下面格式:


< bean   id = "helloWorld"   class = "com.chenzehe.spring.service.impl.HelloWorldImpl" >

< property   name = "personDao" >

< bean   class = "com.chenzehe.spring.dao.impl.PersonDao"   />

</ property >

</ bean > 
 

 

6、 一般属性的注入

    给bean 对象 HelloWorldImpl 添加一个 String 类型的属性 name ,一个 Integer 类型的属性 id ,添加 set get 方法,添加一个三个属性的构造函数。

修改spring 配置文件为:


< bean   id = "personDao"   class = "com.chenzehe.spring.dao.impl.PersonDao"   />

< bean   id = "helloWorld"   class = "com.chenzehe.spring.service.impl.HelloWorldImpl" >

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

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

< property   name = "id"   value = "25"   />

</ bean > 
 

修改属性描述类PropertyDefinition ,添加一个描述属性 value ,设置 get set 方法。

修改注入实现核心代码ClassPathXmlApplicationContext ,先加入 commons-beanutils 包的依赖,用其取得一般类型的属性。

<dependency>

<groupId>commons-beanutils</groupId>

<artifactId>commons-beanutils</artifactId>

<version>1.8.3</version>

</dependency>

修改解析xml 文件类,把一般类型的属性信息也加进去:


        private void initBeansFromXML(String xmlFilePath) {
		try {
			Document doc = Jsoup.parse(new File(xmlFilePath), "UTF-8");
			Elements beanElements = doc.getElementsByTag("bean");
			for (Element element : beanElements) {
				String id = element.attr("id");
				String classPath = element.attr("class");
				BeanDefinition bean = new BeanDefinition(id, classPath);
				// 取得所有属性元素
				Elements propertyElements = element.getElementsByTag("property");
				for (Element propertyElement : propertyElements) {
					String propertyName = propertyElement.attr("name");
					String propertyRef = propertyElement.attr("ref");
					String propertyValue = propertyElement.attr("value");
					PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName, propertyRef, propertyValue);
					// 把属性元素定义添加到bean定义中
					bean.getPropertys().add(propertyDefinition);
				}
				beans.add(bean);
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}
 

 

修改注入方法:


    private void injectObject() {
		// 循环所有bean
		for (BeanDefinition beanDefinition : beans) {
			Object bean = beansClass.get(beanDefinition.getId());
			if (bean != null) {
				try {
					PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
					for (PropertyDefinition propertyDefinition : beanDefinition.getPropertys()) {
						for (PropertyDescriptor propertyDescriptor : ps) {
							if (propertyDefinition.getName().equals(propertyDescriptor.getName())) {
								Method setterMethod = propertyDescriptor.getWriteMethod();// 获取setter方法
								if (setterMethod != null) {
									Object value = null;
									if (StringUtils.isBlank(propertyDefinition.getValue())) {
										value = beansClass.get(propertyDefinition.getRef());
									}
									else {
										value = ConvertUtils.convert(propertyDefinition.getValue(), propertyDescriptor.getPropertyType());
									}
									setterMethod.setAccessible(true);
									setterMethod.invoke(bean, value);// 把引用对象注入到属性中
								}
								break;
							}
						}
					}
				}
				catch (Exception e) {
					// TODO: handle exception
				}
			}
		}
	}
	
 

 

分享到:
评论

相关推荐

    使用反射和注解模拟Spring的依赖注入

    这篇博客"使用反射和注解模拟Spring的依赖注入"探讨了如何通过基本的Java特性来实现类似Spring的功能。我们将深入探讨反射和注解这两个关键概念,以及它们如何在模拟依赖注入中发挥作用。 首先,让我们理解反射的...

    Spring简单模拟Spring容器

    标题中的“Spring简单模拟Spring容器”意味着我们将探讨Spring框架的核心特性——IoC(Inversion of Control,控制反转)和DI(Dependency Injection,依赖注入),以及如何通过编程方式模拟Spring容器的工作原理。...

    模拟Spring的IOC

    **模拟Spring的IOC** 在Java世界中,Spring框架以其强大的依赖注入(Dependency Injection,简称DI)和控制反转(Inversion of Control,简称IOC)能力,成为企业级应用开发的首选框架之一。理解并模拟Spring的IOC...

    Java模拟spring实现

    在本文中,我们将探讨如何通过Java来模拟Spring框架的基本功能。Spring是一个广泛应用的开源框架,它主要为Java应用程序提供依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented Programming,AOP...

    模拟spring的xml配置文件注入

    本文将深入探讨如何模拟Spring的XML配置文件注入,并通过SAXBuilder解析XML文件来实现这一过程。 首先,理解XML配置文件在Spring中的作用至关重要。XML配置文件用于声明应用程序中的bean及其依赖关系,例如类的实例...

    java模拟spring ioc

    这篇博客“java模拟spring ioc”很可能是探讨如何在没有Spring框架的情况下,使用纯Java代码来实现类似Spring的IOC功能。以下将详细介绍Spring的IOC和DI概念以及如何模拟这些概念。 **依赖注入(Dependency ...

    自己动手模拟spring

    【标题】:“自己动手模拟spring” 【描述】:在该主题中,我们将深入理解Spring框架的核心概念,并通过编码实践来模拟其工作原理。参考链接提供了一个CSDN博客文章,作者详细介绍了如何从零开始创建一个简易版的...

    java 解析xml,模拟spring框架ioc

    7. **初始化Bean**:如果Bean实现了InitializingBean接口或者定义了`init-method`属性,Spring会在所有属性注入完成后调用特定的方法来进行初始化。 模拟Spring的IOC功能,我们可以创建一个简单的解析器类,该类...

    模拟Spring IoC

    在这个模拟Spring IoC的项目中,我们可以深入理解以下几个关键知识点: 1. **容器的概念**:Spring IoC容器是管理对象及其依赖关系的核心组件。在这个模拟项目中,会有一个类或接口扮演容器的角色,负责创建对象、...

    模拟spring

    《模拟Spring:深入理解与实践》 在软件开发领域,Spring框架无疑是最为广泛使用的Java企业级应用框架之一。它以其强大的依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented Programming,AOP)...

    简单模拟Spring的beanFactory

    本文将通过模拟Spring的`BeanFactory`来深入理解其工作原理,帮助开发者更好地掌握Spring的核心概念。 `BeanFactory`是Spring框架中最基础的bean管理容器,它是所有更高级别的容器(如`ApplicationContext`)的基类...

    一个模拟Spring将SessionFactory注入到HibernateTemplate的小例子

    在Spring框架中,整合Hibernate是常见的操作,Spring通过其强大的依赖注入(DI)特性,能够帮助我们更好地管理和控制SessionFactory以及与Hibernate相关的操作。本示例将深入探讨如何使用Spring将SessionFactory注入...

    模拟Spring架构的简易实现

    1. **BeanDefinition**:模拟Spring中Bean的定义,包含Bean的类名、属性值、依赖关系等信息。 2. **BeanFactory**:模拟Spring的Bean工厂,负责创建和管理Bean实例,实现依赖注入。 3. **ApplicationContext**:模拟...

    模拟Spring的Ioc功能

    如果存在属性注入,反射也可以用来设置这些属性的值。例如,找到setter方法并调用它们,传入对应的属性值。 5. **依赖注入**:IoC的一个关键部分是处理bean之间的依赖关系。通过解析XML中`&lt;bean&gt;`的属性,我们可以...

    模拟spring ioc技术

    本篇文章将详细解析“模拟Spring IOC技术”的核心概念,并通过一个小Demo帮助你深入理解IOC的工作原理。 首先,我们来解释一下什么是IOC和DI。控制反转(IOC)是编程中的一个设计原则,它改变了对象获取依赖的方式...

    模拟spring中的ClassPathXmlApplicationContext类的实现

    如果bean定义中有`ref`属性,Spring会查找并注入对应的bean实例。 8. **初始化回调**:在所有必需的属性设置完成后,Spring会调用bean的初始化方法(如果有`init-method`属性指定的话)。 9. **上下文刷新**:`...

    Spring中的方法注入

    综上所述,Spring中的方法注入提供了更灵活的方式来管理和注入依赖,它与构造函数注入、属性注入等一起,构成了Spring强大的依赖注入机制。理解并合理使用这些注入方式,可以帮助我们编写出更加健壮、易于维护的代码...

    模拟spring IOC非常好的事例

    下面我们将深入探讨这个"模拟spring IOC非常好的事例"所涵盖的知识点。 首先,我们需要理解什么是IOC。IOC是一种设计模式,它的主要思想是将对象的创建和管理权交给一个外部容器,而不是由对象自身来负责。这样可以...

    Java模拟的spring实现

    总结起来,模拟Spring的实现是一个深度学习Spring框架的过程,它涵盖了依赖注入、面向切面编程、事件机制、事务管理和组件扫描等多个核心部分。这样的实践项目可以帮助我们更好地理解和运用Spring框架,并且可以作为...

    Spring.Net依赖注入例子

    4. **测试与解耦**:依赖注入使得测试变得容易,因为我们可以使用不同的依赖实例(比如模拟对象或存根)来替换实际的依赖,从而进行单元测试。同时,由于对象的创建和依赖关系的管理都交给了Spring,代码之间的耦合...

Global site tag (gtag.js) - Google Analytics