`
NeverSky
  • 浏览: 2865 次
  • 性别: Icon_minigender_1
最近访客 更多访客>>
社区版块
存档分类
最新评论

Spring模拟——BeanFactory

阅读更多

续上篇,在解决完配置文件的解析之后,写了一个简单addUser模块准备测试

model代码:

package com.l.model;

public class User {
	
	private String name;
	private String password;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
}

 DAO(接口代码未贴出)

package com.l.impl;

import com.l.dao.UserDAO;
import com.l.model.User;

public class UserDAOImpl implements UserDAO {

	@Override
	public void save(User u) {
		System.out.println("Success!");
	}

}

UserService代码:

 

package com.l.service;

import com.l.dao.UserDAO;
import com.l.model.User;

public class UserService {
	        private UserDAO dao;//标红
		public UserDAO getUserDAO() {
			return dao;
		}
		public void setUserDAO(UserDAO dao) {
			this.dao = dao;
		}
		public void add(User user) {
			dao.save(user);
		}

}
 

 

 下面进行测试:

package com.l.service;

import java.io.IOException;

import org.junit.Test;

import com.l.impl.UserDAOImpl;
import com.l.model.User;

public class UserServiceTset {
	@Test
	public void addTest() throws IOException, Exception{	
		UserService service = new UserService();
		User u = new User();
		service.add(u);
	}
}

 当你测试完,会报一个空指针错误,这是因为UserService中没有new一个UserDAO对象,这就是spring的好处,不用自己进行手动创建对象。是怎么实现的呢?

在spring中有这样一个配置文件,叫beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans>
	<bean id="u" class="com.l.impl.UserDAO">
        </bean>
</beans>

 使用上篇的方法对其进行解析

package com.l.spring;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;

public class ClassPathXMLApplicationContext implements BeanFactory{
	
	private Map<String, Object> beans = new HashMap<String, Object>();
	
	
	public ClassPathXMLApplicationContext() throws Exception, IOException{
		SAXBuilder builder = new SAXBuilder();
		Document doc = builder.build(this.getClass()
				.getClassLoader().getResourceAsStream("beans.xml"));
		Element root = doc.getRootElement();
		List<Element> elements = root.getChildren("bean");
		
		for (int i = 0; i < elements.size(); i++) {
			Element element = elements.get(i);
			
			String id = element.getAttributeValue("id");
			String clazz = element.getAttributeValue("class");//获取UserDAO的类名
			System.out.println(id + " : " + clazz);
			
			Object o = Class.forName(clazz).newInstance();//为UserDAO创建一个对象
			
			beans.put(id, o);
		}
		
	}
	@Override
        //通过getBean获取为UserDAO创建的对象
	public Object getBean(String id) {
		return beans.get(id);
	}
	
}

通过解析beans.xml中的类名,为其创建对象,实现BeanFactory中的getBea()方法,让外界获取该对象

BeanFactory接口:

package com.l.spring;

public interface BeanFactory {
	public Object getBean(String name);
}

  再次对其进行测试:

package com.l.service;

import java.io.IOException;

import org.junit.Test;

import com.l.impl.UserDAOImpl;
import com.l.model.User;
import com.l.spring.BeanFactory;
import com.l.spring.ClassPathXMLApplicationContext;

public class UserServiceTset {
	@Test
	public void addTest() throws IOException, Exception{
		BeanFactory factory = new ClassPathXMLApplicationContext();
		
		UserService service = new UserService();
		UserDAO userDAO = (UserDAO) factory.getBean("u");

		service.setUserDao(userDAO);
		User u = new User();
		u.setName("nimA");
		u.setPassword("heh");
		service.add(u);
	}
}

 通过测试

 

通过BeanFactory来实例化,管理对象,使用它的实现类ClassPathXmlApplicationContext来新建对象,将配置文件中对应的id和对象放入Map中。

 

再想一下,既然UserDAO可以这样来实现,那么UserService也是可以的:

在beans.xml中加入再添加一个bean标签<bean id="userService" class="com.l.service.UserService">

测试代码:

 

package com.l.service;

import java.io.IOException;

import org.junit.Test;

import com.l.impl.UserDAOImpl;
import com.l.model.User;
import com.l.spring.BeanFactory;
import com.l.spring.ClassPathXMLApplicationContext;

public class UserServiceTset {
	@Test
	public void addTest() throws IOException, Exception{
		BeanFactory factory = new ClassPathXMLApplicationContext();
		
                UserDAO userDAO = (UserDAO) factory.getBean("u");
		UserService service = (UserService)factory.getBean("userService");//标红
		service.setUserDao(userDAO);
		User u = new User();

		service.add(u);
	}
}
代码中标红部分, 分两次调用了getBean方法,然而却是没有这个必要的。在bean.xml中<bean>下添加一个子标签<property>

 

 

<?xml version="1.0" encoding="UTF-8"?>
<beans>
	<bean id="u" class="com.l.impl.UserDAOImpl"/>
	<bean id="userService" class="com.l.service.UserService">
		<property name="userDAO" bean="u"/>
	</bean>
</beans>
 property是告诉你,“userService”中有一个setUserDAO的方法,当调用该方法时,将后面指定的bean传进去,这种方法叫做注入:

 

注入代码:

 

List<Element> property = element.getChildren("property");
			for(Element propertyElement : property) {
		    	   String name = propertyElement.getAttributeValue("name"); //userDAO
		    	   String bean = propertyElement.getAttributeValue("bean"); //u
		    	   Object beanObject = beans.get(bean);//UserDAOImpl instance
		    	   
		    	   String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
		
		    	   Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]);
		    	  // System.out.println(m.getName());
		    	   m.invoke(o, beanObject);
		       }
 将这段代码加到解析bean.xml的java文件的for循环中,此处用到的是反射机制,通过解析配置文件,Map中存有<"u", 相应对象><"userService", 相应对象>,配置文件中第一个<bean>标签下没有<property>,循环至第二个,即"userService" 取出”userService“中的setUserDAO方法,最后通过invoke(obj,args)实现注入,参数obj为调用该方法的对象(此处为o),参数args为取出方法的参数setUserDAO的参数为为一个UserDAO对象,而beanObject就是该类型。

 

test代码:

 

package com.l.service;

import java.io.IOException;

import org.junit.Test;

import com.l.impl.UserDAOImpl;
import com.l.model.User;
import com.l.spring.BeanFactory;
import com.l.spring.ClassPathXMLApplicationContext;

public class UserServiceTset {
	@Test
	public void addTest() throws IOException, Exception{
		BeanFactory factory = new ClassPathXMLApplicationContext();
		
		UserService service = (UserService)factory.getBean("userService");

		User u = new User();
		service.add(u);
	}
}
 

 测试通过,从原理上了解IOC更好的开始学习spring

 

分享到:
评论

相关推荐

    Java模拟的spring实现

    首先,让我们来看看Spring的核心概念——依赖注入(Dependency Injection,简称DI)。依赖注入是将对象之间的依赖关系交给容器管理,而不是由对象自身负责。在模拟实现中,我们可以创建一个类`BeanFactory`,它负责...

    spring2.0和spring2.5 及以上版本的jar包区别 spring jar 包详解

    在Spring2.0时代,为了方便开发者快速构建应用程序,提供了一个包含几乎所有核心功能的单一jar包——`spring.jar`。这个单一的jar包几乎包含了除了`spring-mock.jar`之外的所有内容,因为`spring-mock.jar`主要是在...

    手动打造自己的spring

    总的来说,“手动打造自己的spring”涵盖了Spring的核心组件和设计理念,包括依赖注入的实现、bean工厂和ApplicationContext的构建、AOP和事务管理的模拟,以及数据访问的支持。通过亲手实践,你可以更深入地理解...

    动手写框架,模拟简易的SpringIOC.rar

    标题 "动手写框架,模拟简易的Spring IOC" 暗示了这个压缩包包含了一个教程或实践项目,目的是帮助我们理解Spring框架的核心组件——控制反转(Inversion of Control,简称IOC)。Spring框架是Java开发中广泛使用的...

    Spring3.1Jar包

    5. **测试**:Spring提供了一套完整的测试工具集,包括模拟对象、测试上下文框架以及对JUnit和TestNG的支持,帮助开发者编写可测试的代码。 6. **消息**:Spring的Message模块支持消息传递,尤其是Java消息服务...

    spring 3 企业应用开发

    - **易于测试**:由于对象之间的依赖关系可以轻松地通过Spring容器进行模拟或替换,因此更容易编写单元测试。 - **易于维护和扩展**:当需要更改某个对象的依赖关系时,只需要修改Spring配置文件即可,无需修改...

    Spring的经典面试题

    - **Spring IoC容器**:Spring的IoC容器主要由两个包组成——`org.springframework.beans`和`org.springframework.context`。其中`org.springframework.beans`主要提供Bean操作的基本支持,而`org.springframework....

    详解如何在低版本的Spring中快速实现类似自动配置的功能

    Spring还提供了另一个扩展点——**BeanPostProcessor**,它允许我们对已经创建的Bean实例进行定制逻辑回调,比如在Bean创建后执行特定操作。 关于Bean的定制,有以下几种常见方式: 1. **Lifecycle Callback**:...

    Spring1.2API

    Spring TestContext框架提供了对Spring应用上下文的加载和销毁,以及模拟bean的能力。 在Spring1.2 API文档中,你可以找到以下内容: - **Bean的配置**:XML配置是当时的主要方式,通过`&lt;bean&gt;`标签定义bean及其...

    Spring.3.x企业应用开发实战(完整版).part2

     《Spring3.x企业应用开发实战》是在《精通Spring2.x——企业应用开发详解》的基础上,经过历时一年的重大调整改版而成的,本书延续了上一版本追求深度,注重原理,不停留在技术表面的写作风格,力求使读者在熟练...

    spring ioc

    标题“spring ioc”指的是Spring框架中的核心特性——Inversion of Control(控制反转),也称为依赖注入(Dependency Injection)。在Spring框架中,IOC是通过容器来管理对象的生命周期和对象之间的依赖关系,使得...

    javaee 习题答案.docx完整详细

    Java EE 框架整合开发入门到实战——Spring+SpringMVC+MyBatis(微课版)习题答案详细解析 Java EE 框架整合开发入门到实战——Spring+SpringMVC+MyBatis(微课版)习题答案详细解析中,涵盖了 Spring 框架的核心...

    spring+framwork

    在描述中提到的"spring3的所有源码和doc文档资料",指的是Spring框架的第三个主要版本——Spring 3.0.5。这个版本在2010年发布,引入了许多增强和新功能,包括对Java EE 6的支持、JSR-303(Bean Validation)集成、...

    spring-framework

    1. **核心容器**:这是Spring框架的基础,包括Bean工厂(BeanFactory)和应用上下文(ApplicationContext)。Bean工厂负责管理对象的生命周期和依赖关系,而ApplicationContext则提供了更多的企业级服务,如消息源、...

    Spring3.x企业应用开发实战(完整版) part1

     《Spring3.x企业应用开发实战》是在《精通Spring2.x——企业应用开发详解》的基础上,经过历时一年的重大调整改版而成的,本书延续了上一版本追求深度,注重原理,不停留在技术表面的写作风格,力求使读者在熟练...

    【框架源码篇 01】Spring源码-手写IOC

    在本系列的第一篇中,我们将深入探讨Spring框架的核心特性——依赖注入(Dependency Injection,简称DI),并通过手动实现一个简易的IOC容器来理解其工作原理。Spring框架是Java开发中的基石,它提供了许多功能,如...

    用java写的一个简单的ioc实现,初学的朋友可以看看

    首先,`BeanFactory.java`很可能是模拟Spring的`ApplicationContext`或`BeanFactory`,它是IOC容器的核心,负责管理和实例化对象。在Spring中,`BeanFactory`是一个接口,用于加载和管理Bean定义,提供Bean的实例。...

    4.2.5jar.rar

    标题中的"4.2.5jar.rar"是一个压缩文件,其中包含了Spring框架的特定版本——4.2.5的jar包。Spring是一个广泛使用的Java应用程序框架,主要用于开发企业级应用,它提供了许多功能,如依赖注入、面向切面编程(AOP)...

Global site tag (gtag.js) - Google Analytics