`
yaoweinan
  • 浏览: 132643 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

写自己的框架,让别人笑掉大牙吧(IOC2)

 
阅读更多

    上篇中主要使用配置文件来定义一些类实例之间的组织关系,这篇所要做的就是将其扩展,实现支持自定义化的注解,也就是使用注解来完成配置类实例之间的组织关系。废话不多,请看配置文件:

 

<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="test" class="com.sample.spring1.egclasses.Test" single="true"/>
<autoScan package="com.sample.spring1.egclasses"/>

</beans>

 此配置文件说明了我们框架将会扫描的范围。

再看一下我们自定义的几个annotation

package com.sample.spring1.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface AutoSet {
	public String id();
}


package com.sample.spring1.annotations;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
 @Retention(RetentionPolicy.RUNTIME)
public @interface Bean {
	public String id();

}

package com.sample.spring1.annotations;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Single {
	public boolean isSingle() default true; 
}

 

再看看我们用来测试的几个类

EgDao

package com.sample.spring1.egclasses;

import com.sample.spring1.annotations.Bean;
import com.sample.spring1.annotations.Single;

 @Bean(id="egDao")
 @Single(isSingle=true)
public class EgDao
{

	public void callMe()
	{
		System.out.println("Dao is called");
	}

}

 

EgSevice

 

 

package com.sample.spring1.egclasses;

import com.sample.spring1.annotations.AutoSet;
import com.sample.spring1.annotations.Bean;

 
@Bean(id="service")
public class EgSevice
{
	@AutoSet(id="egDao")
	private EgDao egDao;
	public void callMe(){
		egDao.callMe();
	}
	public EgDao getEgDao()
	{
		return egDao;
	}
	
}

 

EgService1

package com.sample.spring1.egclasses;

import com.sample.spring1.annotations.AutoSet;
import com.sample.spring1.annotations.Bean;

 
@Bean(id="service1")
public class EgSevice1
{
	@AutoSet(id="egDao")
	private EgDao egDao;
	public void callMe(){
		egDao.callMe();
	}
	public EgDao getEgDao()
	{
		return egDao;
	}
	
}

ClassLoader 还试上文用到的并没有做什么特殊的处理

接下来就是我们框架的核心了

package com.sample.spring1;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.Enumeration;
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;

import com.sample.spring1.annotations.AutoSet;
import com.sample.spring1.annotations.Single;

public class SampleSpringContainer
{
	private static final Map<String,Bean> beans=new HashMap<String, Bean>();
	static final Map<String,Object> singles=new HashMap<String, Object>();
	static{
		 SAXBuilder sb = new SAXBuilder();
	     try
		{
			Document doc =sb.build(SampleSpringContainer.class.getClassLoader().getResourceAsStream("com/sample/spring1/springSample.xml"));
			Element rootElement = doc.getRootElement();
			List<Element> beans = rootElement.getChildren("bean");
			buidXmlBeans(beans);
			List<Element> AnnotactionBeans = rootElement.getChildren("autoScan");
			if(!AnnotactionBeans.isEmpty()){
				buildAnnotationBeans(AnnotactionBeans);
			}
			initBeans();
		
		}
		catch (JDOMException e)
		{
			e.printStackTrace();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}
	private static void buidXmlBeans(List<Element> beans){
		for(Element bean :beans){
			String id = bean.getAttributeValue("id");
			if(SampleSpringContainer.beans.containsKey(id))continue;
			String clas = bean.getAttributeValue("class");
			boolean single =Boolean.valueOf(bean.getAttributeValue("single"));
			Bean mbean=new Bean(clas, single);
			SampleSpringContainer.beans.put(id, mbean);
			List<Element> dependences = bean.getChildren("setProperty");
			for(Element dependence :dependences){
				String name = dependence.getAttributeValue("name");
				String agr = dependence.getAttributeValue("refer");
				Bean dbean2 = SampleSpringContainer.beans.get(agr);
				if(dbean2==null){
					buidDependenceBeans(beans,agr);
					dbean2=SampleSpringContainer.beans.get(agr);
				}
				if(dbean2==null){
					throw new IllegalArgumentException(id+"property "+name+"is not found");
				}
				mbean.getDependence().put(name, dbean2);
			}
		}
	}
	private static void buildAnnotationBeans(List<Element> annotactionBeans) throws IOException
	{
		for(Element el:annotactionBeans){
			String packgetName = el.getAttributeValue("package");
		    buildbyPackage(packgetName);
		}
	}
	private static void buildbyPackage(String packgetName) throws IOException
	{
		SampleClassLoader classLoader = SampleClassLoader.getClassLoader();
		String fileResource = packgetName.replace('.', '/');
		Enumeration<URL> resources = classLoader.getResources(fileResource);
		if(resources.hasMoreElements()){
			URL url=resources.nextElement();
			File file = new File(url.getFile());
			for(String f:file.list()){
				System.out.println(f);
				String[] split = f.split("\\.");
				if(split.length==1){
					//TODO load sub package
					buildbyPackage(packgetName+"."+f);
					continue;
				}
				if(split.length<2)continue;
				if(split[1].equals("class")){
					try
					{
						Class<?> loadClass = classLoader.loadClass(packgetName+"."+split[0]);
						Annotation[] classAnnotations = loadClass.getDeclaredAnnotations();
						com.sample.spring1.annotations.Single isSingle=null;
						com.sample.spring1.annotations.Bean beanAn=null;
						for(Annotation an:classAnnotations){
							if(an instanceof com.sample.spring1.annotations.Bean){
								beanAn= (com.sample.spring1.annotations.Bean) an;
								continue;
							}
							if(an instanceof Single){
								isSingle=(Single) an;
							}
						}
						if(beanAn!=null){
							buildBean(loadClass,beanAn,isSingle);
						}
					}
					catch (ClassNotFoundException e)
					{
						e.printStackTrace();
					}
				}
			}
			
		}else{
			throw new IllegalArgumentException(packgetName+" can't be found!");
		}
	}
	private static void buildBean(Class<?> loadClass, com.sample.spring1.annotations.Bean beanAn,
		Single isSingle)
	{
		Bean bean= new Bean(loadClass.getName(), isSingle==null?false:isSingle.isSingle());
		SampleSpringContainer.beans.put(beanAn.id(), bean);
		Field[] fiels = loadClass.getDeclaredFields();
		for(Field f:fiels){
			Annotation[] annotations = f.getAnnotations();
			AutoSet autoProperty=null;
			for(Annotation an:annotations){
				if(an instanceof AutoSet){
					autoProperty=(AutoSet) an;
					break;
				}
			}
			if(autoProperty!=null){
				Bean bean2 = SampleSpringContainer.beans.get(autoProperty.id());
				if(bean2==null){
					Class<? extends Field> class1 = f.getClass();
					Annotation[] classAnnotations = class1.getDeclaredAnnotations();
					com.sample.spring1.annotations.Single isSinglePro=null;
					com.sample.spring1.annotations.Bean beanAnPro=null;
					for(Annotation an:classAnnotations){
						if(an instanceof com.sample.spring1.annotations.Bean){
							beanAnPro= (com.sample.spring1.annotations.Bean) an;
							continue;
						}
						if(an instanceof Single){
							isSinglePro=(Single) an;
						}
					}
					if(beanAnPro!=null){
						buildBean(class1,beanAnPro,isSinglePro);
					}
					bean2 = SampleSpringContainer.beans.get(autoProperty.id());
					
				}
				bean.getDependence().put(f.getName(), bean2);
			}
			
		}
		
	}
	private static void initBeans()
	{
		for(Map.Entry<String, Bean> bean:beans.entrySet()){
			if(!bean.getValue().getDependence().isEmpty()){
				for(Map.Entry<String, Bean> dep:bean.getValue().getDependence().entrySet()){
					deepBuildDependence(dep.getValue().getDependence());
				}
			}
			singles.put(bean.getValue().getClassName(), bean.getValue().newInstance());
		}
		
	}
	private static void deepBuildDependence(Map<String, Bean> dependence)
	{
		for(Map.Entry<String, Bean> dep:dependence.entrySet()){
			Bean bean = dep.getValue();
			if(!bean.getDependence().isEmpty()){
				deepBuildDependence(bean.getDependence());
			}
			singles.put(bean.getClassName(), bean.newInstance());
		}
		
	}
	private static void buidDependenceBeans(List<Element> beans,final String rid){
		for(Element bean :beans){
			String id = bean.getAttributeValue("id");
			if(!rid.equals(id))continue;
			String clas = bean.getAttributeValue("class");
			boolean single =Boolean.valueOf(bean.getAttributeValue("single"));
			Bean mbean=new Bean(clas, single);
			SampleSpringContainer.beans.put(id, mbean);
			List<Element> dependences = bean.getChildren("setProperty");
			for(Element dependence :dependences){
				String name = dependence.getAttributeValue("name");
				String agr = dependence.getAttributeValue("refer");
				Bean dbean2 = SampleSpringContainer.beans.get(agr);
				if(dbean2==null){
					buidDependenceBeans(beans,agr);
					dbean2=SampleSpringContainer.beans.get(agr);
				}
				if(dbean2==null){
					throw new IllegalArgumentException("");
				}
				mbean.getDependence().put(name, dbean2);
			}
		}
		
	}
	public static Object getBean(final String beanId){
		Bean bean = beans.get(beanId);
		if(bean!=null){
			if(bean.isSingle()){
				return singles.get(beanId);
			}else{
				return bean.newInstance();
			}
		}
		return null;
	}
}
class Bean{
	private String className;
	private boolean isSingle;
	
	public Bean(String className, boolean isSingle)
	{
		super();
		this.className = className;
		this.isSingle = isSingle;
	}

	private Map<String,Bean> dependence=new HashMap<String, Bean>();
	
	public String getClassName()
	{
		return className;
	}
	public void setClassName(String className)
	{
		this.className = className;
	}
	public boolean isSingle()
	{
		return isSingle;
	}
	public Map<String, Bean> getDependence()
	{
		return dependence;
	}
	
	public Object newInstance(){
		SampleClassLoader classLoader = SampleClassLoader.getClassLoader();
		Object newInstance=null;
		try
		{
			Class<?> loadClass = classLoader.loadClass(className);
			newInstance= loadClass.newInstance();
			for(Map.Entry<String, Bean> entity:dependence.entrySet()){
				Field field = loadClass.getDeclaredField(entity.getKey());
				field.setAccessible(true);
				if(entity.getValue().isSingle()){
					field.set(newInstance,SampleSpringContainer.singles.get(entity.getValue().getClassName()));
				}else{
					field.set(newInstance, entity.getValue().newInstance());
				}
			}
		}
		catch (ClassNotFoundException e)
		{
			e.printStackTrace();
		}
		catch (InstantiationException e)
		{
			e.printStackTrace();
		}
		catch (IllegalAccessException e)
		{
			e.printStackTrace();
		}
		catch (SecurityException e)
		{
			e.printStackTrace();
		}
		catch (NoSuchFieldException e)
		{
			e.printStackTrace();
		}
		return newInstance;
	}
}

 

这个类是在上篇中的类在做了一些修改 实现了对annotation的支持

 

下面依旧,是个测试

package com.sample.spring1;

import com.sample.spring1.egclasses.EgSevice;
import com.sample.spring1.egclasses.EgSevice1;

public class TestSpring
{

	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		EgSevice bean = (EgSevice) SampleSpringContainer.getBean("service");
		bean.callMe();
		EgSevice1 bean1 = (EgSevice1) SampleSpringContainer.getBean("service1");
		bean1.callMe();
		System.out.println(bean.getEgDao()==bean1.getEgDao());

	}

}

 

 

  • 大小: 16.7 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics