- 浏览: 538244 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
c__海棠依旧:
很强,对于我这个新手很容易理解,准们登录来给你点赞的!
BeanFactory和FactoryBean -
hudazheng:
很清晰!
X86、X64和X86_64区别 -
hugh.wang:
...
BeanFactory和FactoryBean -
CB00J:
...
Executor框架和线程池 -
Arbow:
请教一个问题。现在互联网业务的数据库通常用分片方式来连接一组数 ...
BoneCP源码——概述
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事务
2016-06-29 11:59 0在学习spring事务管理时,我忍不住要问,spring为 ... -
深入浅出 Spring AOP 动态代理 CGLib Aspectj
2013-05-29 17:50 42560、AOP实现原理 面向方面编程(Aspect O ... -
模拟Spring生成Bean
2012-04-17 20:15 30351、 原理 读取 Spring配置文件,解析 ... -
BeanFactory和FactoryBean
2012-04-10 10:20 449801、 BeanFactory BeanFa ... -
Spring / Hibernate / JUnit - No Hibernate Session bound to Thread
2012-03-29 08:55 1568在spring mvc中使用junit单元测试时,没有取到hi ... -
org.springframework.web.servlet.DispatcherServlet cannot be cast to javax.servle
2012-03-28 10:50 21645调试Spring MVC时发现如下异常: java.la ... -
Spring的基本概念和MVC环境搭建
2012-03-23 11:52 17421、 Spring介绍 打开Spring 官 ...
相关推荐
这篇博客"使用反射和注解模拟Spring的依赖注入"探讨了如何通过基本的Java特性来实现类似Spring的功能。我们将深入探讨反射和注解这两个关键概念,以及它们如何在模拟依赖注入中发挥作用。 首先,让我们理解反射的...
标题中的“Spring简单模拟Spring容器”意味着我们将探讨Spring框架的核心特性——IoC(Inversion of Control,控制反转)和DI(Dependency Injection,依赖注入),以及如何通过编程方式模拟Spring容器的工作原理。...
**模拟Spring的IOC** 在Java世界中,Spring框架以其强大的依赖注入(Dependency Injection,简称DI)和控制反转(Inversion of Control,简称IOC)能力,成为企业级应用开发的首选框架之一。理解并模拟Spring的IOC...
在本文中,我们将探讨如何通过Java来模拟Spring框架的基本功能。Spring是一个广泛应用的开源框架,它主要为Java应用程序提供依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented Programming,AOP...
本文将深入探讨如何模拟Spring的XML配置文件注入,并通过SAXBuilder解析XML文件来实现这一过程。 首先,理解XML配置文件在Spring中的作用至关重要。XML配置文件用于声明应用程序中的bean及其依赖关系,例如类的实例...
这篇博客“java模拟spring ioc”很可能是探讨如何在没有Spring框架的情况下,使用纯Java代码来实现类似Spring的IOC功能。以下将详细介绍Spring的IOC和DI概念以及如何模拟这些概念。 **依赖注入(Dependency ...
【标题】:“自己动手模拟spring” 【描述】:在该主题中,我们将深入理解Spring框架的核心概念,并通过编码实践来模拟其工作原理。参考链接提供了一个CSDN博客文章,作者详细介绍了如何从零开始创建一个简易版的...
7. **初始化Bean**:如果Bean实现了InitializingBean接口或者定义了`init-method`属性,Spring会在所有属性注入完成后调用特定的方法来进行初始化。 模拟Spring的IOC功能,我们可以创建一个简单的解析器类,该类...
在这个模拟Spring IoC的项目中,我们可以深入理解以下几个关键知识点: 1. **容器的概念**:Spring IoC容器是管理对象及其依赖关系的核心组件。在这个模拟项目中,会有一个类或接口扮演容器的角色,负责创建对象、...
《模拟Spring:深入理解与实践》 在软件开发领域,Spring框架无疑是最为广泛使用的Java企业级应用框架之一。它以其强大的依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented Programming,AOP)...
本文将通过模拟Spring的`BeanFactory`来深入理解其工作原理,帮助开发者更好地掌握Spring的核心概念。 `BeanFactory`是Spring框架中最基础的bean管理容器,它是所有更高级别的容器(如`ApplicationContext`)的基类...
在Spring框架中,整合Hibernate是常见的操作,Spring通过其强大的依赖注入(DI)特性,能够帮助我们更好地管理和控制SessionFactory以及与Hibernate相关的操作。本示例将深入探讨如何使用Spring将SessionFactory注入...
1. **BeanDefinition**:模拟Spring中Bean的定义,包含Bean的类名、属性值、依赖关系等信息。 2. **BeanFactory**:模拟Spring的Bean工厂,负责创建和管理Bean实例,实现依赖注入。 3. **ApplicationContext**:模拟...
如果存在属性注入,反射也可以用来设置这些属性的值。例如,找到setter方法并调用它们,传入对应的属性值。 5. **依赖注入**:IoC的一个关键部分是处理bean之间的依赖关系。通过解析XML中`<bean>`的属性,我们可以...
本篇文章将详细解析“模拟Spring IOC技术”的核心概念,并通过一个小Demo帮助你深入理解IOC的工作原理。 首先,我们来解释一下什么是IOC和DI。控制反转(IOC)是编程中的一个设计原则,它改变了对象获取依赖的方式...
如果bean定义中有`ref`属性,Spring会查找并注入对应的bean实例。 8. **初始化回调**:在所有必需的属性设置完成后,Spring会调用bean的初始化方法(如果有`init-method`属性指定的话)。 9. **上下文刷新**:`...
综上所述,Spring中的方法注入提供了更灵活的方式来管理和注入依赖,它与构造函数注入、属性注入等一起,构成了Spring强大的依赖注入机制。理解并合理使用这些注入方式,可以帮助我们编写出更加健壮、易于维护的代码...
下面我们将深入探讨这个"模拟spring IOC非常好的事例"所涵盖的知识点。 首先,我们需要理解什么是IOC。IOC是一种设计模式,它的主要思想是将对象的创建和管理权交给一个外部容器,而不是由对象自身来负责。这样可以...
总结起来,模拟Spring的实现是一个深度学习Spring框架的过程,它涵盖了依赖注入、面向切面编程、事件机制、事务管理和组件扫描等多个核心部分。这样的实践项目可以帮助我们更好地理解和运用Spring框架,并且可以作为...
4. **测试与解耦**:依赖注入使得测试变得容易,因为我们可以使用不同的依赖实例(比如模拟对象或存根)来替换实际的依赖,从而进行单元测试。同时,由于对象的创建和依赖关系的管理都交给了Spring,代码之间的耦合...