Spring 原理:IOC的概念

本文源码:spring原理     备用下载:spring原理

我们先来回顾一下,在没有使用spring的时候,后台业务是怎么操作的:

一,首先要有一个model(或者称为domain)类,用来存放bean

User.java

package com.haizhu.model;

public class User {
	private String username;
	private String password;
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
}

二:dao操作层,是用来和数据库打交道,执行具体的增删查改

1、dao接口:之所以使用接口是为了跨平台,当你需要oracle的数据库,就按照oracle的要求实现这个dao接口,当你需要mysql数据库就实现mySQL的接口

package com.haizhu.dao;

import com.haizhu.model.User;

public interface UserDao {
	public void addUser(User u);
}

2、daoImpl实现:按照数据库的不同进行不同的具体实现

package com.haizhu.dao.impl;

import com.haizhu.dao.UserDao;
import com.haizhu.model.User;

public class UserDaoImpl implements UserDao {
	@Override
	public void addUser(User u) {
		System.out.println(" A user saved !");
	}
}
注:为了简化范例,这里没有执行数据库的操作,只是将数据输出到控制台。

三:service业务层,用来处理繁杂的业务关系

1、service接口:这里接口是为了对比一般实现方法和使用类似spring注入方法的区别

package com.haizhu.service;

import com.haizhu.model.User;

public interface UserService {
	public void addUser(User u);
}
2、serviceImpl一般实现:没有使用spring的时候,UserDao需要手动初始化

package com.haizhu.service.impl;

import com.haizhu.dao.UserDao;
import com.haizhu.dao.impl.UserDaoImpl;
import com.haizhu.model.User;
import com.haizhu.service.UserService;

// 当使用原始的方法的时候,这么做,来进行初始化
public class SimpleUserServiceImpl implements UserService {
	// 这里UserDao 需要手动实例化,与spring的主要区别就在这里
	private UserDao newUserDao = new UserDaoImpl();

	public void addUser(User u){
		newUserDao.addUser(u);
	}
}

四:测试

package com.haizhu.service.impl;

import org.junit.Test;

import com.haizhu.model.User;
import com.haizhu.service.UserService;

public class SimpleUserServiceImplTest {

	@Test
	public void test() {
		// 实例化一个 UserService,具体的实现是SimpleUserServiceImpl
		UserService service = new SimpleUserServiceImpl();
		// 实际项目中,这个 user 是从页面传递过来的,通过struts在action中进行接收
		User u = new User();
		// 调用dao层的具体操作方法,现实数据库操作
		service.addUser(u);
	}
}

结果:

 A user saved !


下面我们来看看使用配置文件的方式实现上面的功能:

一:注入dao的service实现

package com.haizhu.service.impl;

import com.haizhu.dao.UserDao;
import com.haizhu.model.User;
import com.haizhu.service.UserService;
import com.haizhu.spring.BeanFactory;
import com.haizhu.spring.ClassPathXmlApplicationContext;
// 当使用spring的时候,交给xml配置文件来初始化
public class DIDaoUserServiceImpl implements UserService {
	BeanFactory factory = new ClassPathXmlApplicationContext();
	private UserDao springUserDao = (UserDao) factory.getBean("u");;
	public void addUser(User u) {
		springUserDao.addUser(u);
	}
}

二:定义一个工厂接口BeanFactory,可以通过名字取出对应的UserDaoImpl

package com.haizhu.spring;

public interface BeanFactory {
	public Object getBean(String name);
}
工厂的具体实现

package com.haizhu.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.JDOMException;
import org.jdom2.input.SAXBuilder;

public class ClassPathXmlApplicationContext implements BeanFactory{

	// 作为存储所有 bean 的容器
	private Map<String,Object> beans = new HashMap<String,Object>();
	// 构造方法
	public ClassPathXmlApplicationContext(){
		try {
			SAXBuilder sb = new SAXBuilder();
			Document doc = sb.build(this.getClass().getClassLoader().getResourceAsStream("beans.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 clazz = element.getAttributeValue("class");
				System.out.println(id+":"+clazz);
				Object o= Class.forName(clazz).newInstance();
				// 将这个bean放到beans容器中
				beans.put(id, o);;
			}
		}catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} //构造文档对象
	}
	
	public Object getBean(String name) {
		// 根据名字从beans容器中取出这个bean
		return beans.get(name);
	}

}
三:配置文件 beans.xml

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

四:测试

package com.haizhu.service.impl;

import org.junit.Test;

import com.haizhu.model.User;
import com.haizhu.service.UserService;

public class DIDaoUserServiceImplTest {
	@Test
	public void test() {
		UserService service = new DIDaoUserServiceImpl();
		User u = new User();
		service.addUser(u);
	}
}


上面只是自动注入了dao,service还是需要手动实例化,下面我们将sercie也放入容器:

一:service实现

package com.haizhu.service.impl;

import com.haizhu.dao.UserDao;
import com.haizhu.model.User;
import com.haizhu.service.UserService;
// 当使用spring的时候,交给xml配置文件来初始化
public class SpringUserServiceImpl implements UserService {
	private UserDao userDao;
	
	public void addUser(User u) {
		userDao.addUser(u);
	}

	public UserDao getUserDao() {
		return userDao;
	}
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

}

二:工厂实现

package com.haizhu.spring;

import java.lang.reflect.Method;
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>();

	// IOC Inverse of Control DI Dependency Injection
	public ClassPathXmlApplicationContext() {
		try {
			SAXBuilder sb = new SAXBuilder();
			Document doc = sb.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml"));// 构造文档对象
			Element root = doc.getRootElement(); // 获取根元素HD
			List<?> list = root.getChildren("bean");// 取名字为disk的所有元素
			for (int i = 0; i < list.size(); i++) {
				Element element = (Element) list.get(i);
				String id = element.getAttributeValue("id");
				String clazz = element.getAttributeValue("class");
				Object o = Class.forName(clazz).newInstance();
				System.out.println(id);
				System.out.println(clazz);
				beans.put(id, o);
				for (Element propertyElement : (List<Element>) element.getChildren("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);
					System.out.println("method name = " + methodName);
					Method m = o.getClass().getMethod(methodName,beanObject.getClass().getInterfaces()[0]);
					m.invoke(o, beanObject);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public Object getBean(String id) {
		return beans.get(id);
	}

}

三:修改beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans>
	<bean id="u" class="com.haizhu.dao.impl.UserDaoImpl"></bean>
	<bean id="service" class="com.haizhu.service.impl.SpringUserServiceImpl" >
		<property name="userDao" bean="u"/>
	</bean>
</beans>

四:测试

package com.haizhu.service.impl;

import org.junit.Test;

import com.haizhu.model.User;
import com.haizhu.service.UserService;
import com.haizhu.spring.BeanFactory;
import com.haizhu.spring.ClassPathXmlApplicationContext;

public class SpringUserServiceImplTest {
	@Test
	public void test() {
		// 取出容器中的service
		BeanFactory applicationContext = new ClassPathXmlApplicationContext();
		UserService service = (UserService) applicationContext.getBean("service");
		User u = new User();
		service.addUser(u);
	}
}

一般使用ApplicationContext,替换BeanFactory

package com.haizhu.service.impl;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.haizhu.model.User;
import com.haizhu.service.UserService;

public class UserServiceImplTest extends UserServiceImpl {

	@Test
	public void test() {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
		UserService service = (UserService)ctx.getBean("service");
		User u = new User();
		service.addUser(u);
	}
}


可以看出,使用注入的方式,只需要改变配置文件就可以更改dao的实现,这样灵活性大大提高。











  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值