Spring是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器框架。通过控制反转可以使代码的依赖性降到最低,直接在配置文件中对需要修改的逻辑代码进行修改。通过AOP可以是业务代码更专注于业务逻辑而无需管理日志及其他信息,关于统计和日志信息可以通过切片代码进行管理。
一个简单的IOC的模拟:
我们从建立的测试代码开始:
package com.bjsxt.service;
import org.junit.Test;
import com.bjsxt.dao.UserDAO;
import com.bjsxt.dao.impl.UserDAOImpl;
import com.bjsxt.model.User;
import com.bjsxt.spring.BeanFactory;
import com.bjsxt.spring.ClassPathXmlApplicationContext;
public class UserServiceTest {
@Test
public void testAdd() throws Exception {
BeanFactory applicationContext = new ClassPathXmlApplicationContext();
UserService service = (UserService)applicationContext.getBean("userService");
// UserDAO ud = (UserDAOImpl)applicationContext.getBean("u");
// service.setUserDAO(ud);
User u = new User();
u.setUsername("zhangsan");
u.setPassword("zhangsan");
service.add(u);
}
}
首先第一局建立一个BeanFactory:
BeanFactory applicationContext = new ClassPathXmlApplicationContext();
BeanFactory是一个简单的接口,只有一个抽象方法,getBean():
package com.bjsxt.spring;
public interface BeanFactory {
public Object getBean(String id);
}
ClassPathXmlAppicationContext是一个通过JDOM读取XML到的方法,简单实现只读取了bean,spring的实现比较多:
package com.bjsxt.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() throws Exception {
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);
}
}
}
public Object getBean(String id) {
return beans.get(id);
}
}
对这个类进行初始化之后就把配置的文件都读取到了内存中。使用反射机制。
UserService:
package com.bjsxt.service;
import com.bjsxt.dao.UserDAO;
import com.bjsxt.model.User;
public class UserService {
private UserDAO userDAO;
public void add(User user) {
userDAO.save(user);
}
public UserDAO getUserDAO() {
return userDAO;
}
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
}
UserDao:
package com.bjsxt.dao;
import com.bjsxt.model.User;
public interface UserDAO {
public void save(User user);
}
UserDaoImpl:
package com.bjsxt.dao.impl;
import com.bjsxt.dao.UserDAO;
import com.bjsxt.model.User;
public class UserDAOImpl implements UserDAO {
public void save(User user) {
//Hibernate
//JDBC
//XML
//NetWork
System.out.println("user saved!");
}
}
Spring的IOC处理的就是对配置文件读取及类加载的过程。通过配置文件对java代码进行解耦和。