续上篇,在解决完配置文件的解析之后,写了一个简单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
相关推荐
首先,让我们来看看Spring的核心概念——依赖注入(Dependency Injection,简称DI)。依赖注入是将对象之间的依赖关系交给容器管理,而不是由对象自身负责。在模拟实现中,我们可以创建一个类`BeanFactory`,它负责...
在Spring2.0时代,为了方便开发者快速构建应用程序,提供了一个包含几乎所有核心功能的单一jar包——`spring.jar`。这个单一的jar包几乎包含了除了`spring-mock.jar`之外的所有内容,因为`spring-mock.jar`主要是在...
总的来说,“手动打造自己的spring”涵盖了Spring的核心组件和设计理念,包括依赖注入的实现、bean工厂和ApplicationContext的构建、AOP和事务管理的模拟,以及数据访问的支持。通过亲手实践,你可以更深入地理解...
标题 "动手写框架,模拟简易的Spring IOC" 暗示了这个压缩包包含了一个教程或实践项目,目的是帮助我们理解Spring框架的核心组件——控制反转(Inversion of Control,简称IOC)。Spring框架是Java开发中广泛使用的...
5. **测试**:Spring提供了一套完整的测试工具集,包括模拟对象、测试上下文框架以及对JUnit和TestNG的支持,帮助开发者编写可测试的代码。 6. **消息**:Spring的Message模块支持消息传递,尤其是Java消息服务...
- **易于测试**:由于对象之间的依赖关系可以轻松地通过Spring容器进行模拟或替换,因此更容易编写单元测试。 - **易于维护和扩展**:当需要更改某个对象的依赖关系时,只需要修改Spring配置文件即可,无需修改...
- **Spring IoC容器**:Spring的IoC容器主要由两个包组成——`org.springframework.beans`和`org.springframework.context`。其中`org.springframework.beans`主要提供Bean操作的基本支持,而`org.springframework....
Spring还提供了另一个扩展点——**BeanPostProcessor**,它允许我们对已经创建的Bean实例进行定制逻辑回调,比如在Bean创建后执行特定操作。 关于Bean的定制,有以下几种常见方式: 1. **Lifecycle Callback**:...
Spring TestContext框架提供了对Spring应用上下文的加载和销毁,以及模拟bean的能力。 在Spring1.2 API文档中,你可以找到以下内容: - **Bean的配置**:XML配置是当时的主要方式,通过`<bean>`标签定义bean及其...
《Spring3.x企业应用开发实战》是在《精通Spring2.x——企业应用开发详解》的基础上,经过历时一年的重大调整改版而成的,本书延续了上一版本追求深度,注重原理,不停留在技术表面的写作风格,力求使读者在熟练...
标题“spring ioc”指的是Spring框架中的核心特性——Inversion of Control(控制反转),也称为依赖注入(Dependency Injection)。在Spring框架中,IOC是通过容器来管理对象的生命周期和对象之间的依赖关系,使得...
Java EE 框架整合开发入门到实战——Spring+SpringMVC+MyBatis(微课版)习题答案详细解析 Java EE 框架整合开发入门到实战——Spring+SpringMVC+MyBatis(微课版)习题答案详细解析中,涵盖了 Spring 框架的核心...
在描述中提到的"spring3的所有源码和doc文档资料",指的是Spring框架的第三个主要版本——Spring 3.0.5。这个版本在2010年发布,引入了许多增强和新功能,包括对Java EE 6的支持、JSR-303(Bean Validation)集成、...
1. **核心容器**:这是Spring框架的基础,包括Bean工厂(BeanFactory)和应用上下文(ApplicationContext)。Bean工厂负责管理对象的生命周期和依赖关系,而ApplicationContext则提供了更多的企业级服务,如消息源、...
《Spring3.x企业应用开发实战》是在《精通Spring2.x——企业应用开发详解》的基础上,经过历时一年的重大调整改版而成的,本书延续了上一版本追求深度,注重原理,不停留在技术表面的写作风格,力求使读者在熟练...
在本系列的第一篇中,我们将深入探讨Spring框架的核心特性——依赖注入(Dependency Injection,简称DI),并通过手动实现一个简易的IOC容器来理解其工作原理。Spring框架是Java开发中的基石,它提供了许多功能,如...
首先,`BeanFactory.java`很可能是模拟Spring的`ApplicationContext`或`BeanFactory`,它是IOC容器的核心,负责管理和实例化对象。在Spring中,`BeanFactory`是一个接口,用于加载和管理Bean定义,提供Bean的实例。...
标题中的"4.2.5jar.rar"是一个压缩文件,其中包含了Spring框架的特定版本——4.2.5的jar包。Spring是一个广泛使用的Java应用程序框架,主要用于开发企业级应用,它提供了许多功能,如依赖注入、面向切面编程(AOP)...