spring框架比较基本的特性就是ioc和aop,ioc的基本原理则是使用java的反射编程,当然spring的实际实现过程非常复杂。不过如果我们理解了基本的原理,那么想要实现一个简单的ioc框架也不麻烦。
首先,编写一个容器类SimpleContext,该容器类负责加载初始化配置文件中定义的全路径类名所对应的对象,为了方便,配置文件直接使用properties格式文件。具体如下,初始化方法加上类锁,防止多线程时多次加载。初始化方法还根据配置文件定义区分了单例和非单例,单例在初始化时生成对象,非单例则在实际getBean时初始化。
public class SimpleContext {
private static Map<String, String> beanMap = null;
private static Map<String, Object> singleMap = new HashMap<String, Object>();
private final static String SUFFIX = ".properties";
//私有构造函数
private SimpleContext(){
}
<span style="color:#ff6666;">private static synchronized void initMap() throws Exception{
beanMap = new HashMap<String, String>();
Properties p = new Properties();
p.load(SimpleContext.class.getResourceAsStream("SimpleContext"+SUFFIX));
Set<?> keySet = p.keySet();
Iterator<?> it =keySet.iterator();
while(it.hasNext()){
String beanName = (String)it.next();
String className = p.getProperty(beanName);
System.out.println("加载"+beanName+"所对应的类"+className);
//单例处理
if(beanName.startsWith("single")){
Class<?> clazz = Class.forName(className.toString());
Object singleObj = clazz.newInstance();
// initAnnotation(singleObj);
singleMap.put(beanName, singleObj);
}else{
beanMap.put(beanName, className);
}
}
}
</span>
public static Object getBean(String beanName) throws Exception{
Object instance = null;
if(beanMap==null){
initMap();
}
if(beanName.startsWith("single")){
instance = singleMap.get(beanName);
}else{
String className = beanMap.get(beanName);
Class<?> clazz = Class.forName(className.toString());
instance = clazz.newInstance();
}
if(instance==null){
throw new Exception("找不到"+beanName+",应该是没有配置");
}
return instance;
}
}
properties文件中定义的key=value如下,getBean时通过key获取
#非单例模式
student=ioc.simplespringioc.common.Student
teacher=ioc.simplespringioc.common.Teacher
book=ioc.simplespringioc.common.Book
#单例模式
singlestudent=ioc.simplespringioc.common.Student
singleteacher=ioc.simplespringioc.common.Teacher
singlebook=ioc.simplespringioc.common.Book
最后测试代码如下,student、book类就是简单的dto类,代码不再贴出
/**
* 模拟框架中的ioc,此处为了方便,是在SimpleContext.properties中配置bean,通过SimpleContext获取bean
* 如果增加了新的类则需要在SimpleContext.properties配置
* 简单的使用SimpleContext.properties还是可以实现,至于set属性等则比较难实现,还是需要使用类似xml方便点
*
* */
public class TestSimple {
public static void main(String args[]) throws Exception{
//非单例
Student student = (Student)SimpleContext.getBean("student");
System.out.println("非单例,此处setAge(15)");
student.setAge(15);
student = (Student)SimpleContext.getBean("student");
System.out.println("非单例,不能获取属性:"+student.getAge());
Book book = (Book)SimpleContext.getBean("book");
//单例
Student singlestudent = (Student)SimpleContext.getBean("singlestudent");
System.out.println("单例,此处setAge(15)");
singlestudent.setAge(15);
singlestudent = (Student)SimpleContext.getBean("singlestudent");
System.out.println("单例,能获取属性:"+singlestudent.getAge());
Book singlebook = (Book)SimpleContext.getBean("singlebook");
}
}
输出结果如下:
加载singleteacher所对应的类ioc.simplespringioc.common.Teacher
加载book所对应的类ioc.simplespringioc.common.Book
加载singlebook所对应的类ioc.simplespringioc.common.Book
加载student所对应的类ioc.simplespringioc.common.Student
加载singlestudent所对应的类ioc.simplespringioc.common.Student
加载teacher所对应的类ioc.simplespringioc.common.Teacher
非单例,此处setAge(15)
非单例,不能获取属性:0
单例,此处setAge(15)
单例,能获取属性:15
spring的ioc支持很多生成对象的方式以及属性赋值,如这里的使用默认构造函数的方式,还有其他利用含参数构造函数以及利用set方法赋值等,有兴趣的同学可以自己尝试下