IoC(控制反转)是Spring框架的核心,通过DI(依赖注入)实现对象创建和依赖管理的自动化。Spring本质上就是一个Bean容器,负责完成对象的创建和依赖的注入

所谓控制反转,就是把原先我们代码里面需要实现的对象(bean)创建、依赖的代码,反转给ioc容器来帮忙实现,也就是 ioc 容器帮我们做了原本应该我门自己实现的对象创建和依赖的内容。
我们有一个业务逻辑模块 UserService 和一个实体类 User 还有一个持久层模块 UserDAO 和它的实现 UserDAOImpl。
他们之间 UserService 调用(依赖)UserDAO 来操作数据库。我们在test 中运行的时候呢,要创建 UserService 和 UserDAO 并将 UserDAO set 到 UserService 中,这是我门正常的逻辑。
好了、现在我们要用自己编写的简单的ioc 来处理这些关系。
一、项目结构

1
| ### 二、导入Maven依赖的jar包(pom.xml)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
<groupId>com.study</groupId> <artifactId>simple-springioc</artifactId> <version>1.0-SNAPSHOT</version>
<properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties>
<dependencies> <dependency> <groupId>jdom</groupId> <artifactId>jdom</artifactId> <version>1.0</version> </dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependencies> </project>
`### 三、编写bean.xml```xml <beans> <bean id="u" class="com.study.dao.impl.UserDAOImpl" /> <bean id="userService" class="com.study.service.UserService" > <property name="userDAO" bean="u"/> </bean>
</beans>
|
三、创建BeanFactory接口
创建一个BeanFactory接口用来创建bean (模拟spring)
1 2 3 4 5 6 7 8 9 10
| package com.study.spring;
public interface BeanFactory { Object getBean(String name); }
|
四、创建ClassPathXmlApplicationContext实现类
创建一个用来处理xml的类ClassPathXmlApplicationContext (也是模拟spring)
1 2 3
| import org.jdom.Document; import org.jdom.Element; import org.jdom.input.SAXBuilder;
|
1 2 3 4
| import java.lang.reflect.Method; import java.util.HashMap; import java.util.List; import java.util.Map;
|
1 2
| /** * @author Howe Hsiang
|
*/
1 2
| public class ClassPathXmlApplicationContext implements BeanFactory { private Map<String, Object> beans = new HashMap<String, Object>();
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| public ClassPathXmlApplicationContext() throws Exception { SAXBuilder sb = new SAXBuilder(); Document doc = sb.build("src/main/resources/bean.xml"); Element root = doc.getRootElement(); List list = root.getChildren("bean"); for (int i = 0; i < list.size(); i++) { Element element = (Element) list.get(i); String id = element.getAttributeValue("id"); String className = element.getAttributeValue("class"); System.out.println("id : " + id + " className : " + className); Object o = Class.forName(className).newInstance(); beans.put(id, o);
|
1 2 3 4 5
| //依赖注入,自动装配 xml 的第二层 for (Element propertyElement : (List<Element>) element.getChildren("property")) { String name = propertyElement.getAttributeValue("name"); //userDAO String bean = propertyElement.getAttributeValue("bean"); //u Object beanObj = beans.get(bean);//UserDAOImpl instance
|
1 2 3
| //拼出setUserDAO方法名字 String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1); System.out.println("methodName : " + methodName);
|
1 2 3 4
|
Method m = o.getClass().getMethod(methodName, beanObj.getClass().getInterfaces()[0]);
|
1 2 3 4
| // 进行注入 // 代理执行 m 方法, 也就是用 o 这个对象 调用 m 方法 参数 为 beanObj // o.m(beanObj) 等价于 userService.setUserDao(userDao) m.invoke(o, beanObj);
|
}
1 2
| public Object getBean(String name) { return beans.get(name);
|
}
`### 六、测试类UserServiceTest```java
1
| package com.study.service;
|
1 2 3 4 5 6 7
| import com.study.aop.LogInterceptor; import com.study.dao.UserDAO; import com.study.dao.impl.UserDAOImpl; import com.study.model.User; import com.study.spring.BeanFactory; import com.study.spring.ClassPathXmlApplicationContext; import org.junit.Test;
|
1
| import java.lang.reflect.Proxy;
|
*/
1
| public class UserServiceTest {
|
1 2
| @Test public void testAdd() throws Exception {
|
1 2 3 4
| BeanFactory factory = new ClassPathXmlApplicationContext();
|
1 2 3
| //依赖注入,自动装配 UserService userService = (UserService) factory.getBean("userService"); userService.add(new User());
|
}
1 2 3 4 5 6 7 8 9 10 11 12
| @Test public void testProxy() { UserDAO userDAO = new UserDAOImpl(); LogInterceptor li = new LogInterceptor(); li.setTarget(userDAO);
|
1 2 3 4 5 6 7
| Class[] cl = new Class[1]; cl[0] = UserDAO.class; UserDAO userDAOProxy = (UserDAO) Proxy.newProxyInstance(userDAO.getClass().getClassLoader(), cl, li); System.out.println(userDAOProxy.getClass()); userDAOProxy.detele(); userDAOProxy.save(new User());
|
*/
}
*注:* [简单的Spring-IOC](https://github.com/Hosiang1026/simple-springioc)
本文标题: SpringIOC实战篇
本文作者: 狂欢马克思
发布时间: 2019年03月03日 00:00
最后更新: 2025年12月30日 08:54
原始链接: https://haoxiang.eu.org/ce756b0e/
版权声明: 本文著作权归作者所有,均采用CC BY-NC-SA 4.0许可协议,转载请注明出处!