`
yaoweinan
  • 浏览: 137550 次
  • 性别: 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
分享到:
评论

相关推荐

    springIOC手写框架分析

    springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC...

    自己动手做框架——ORM,MVC,IOC框架

    本教程将聚焦于三个关键的框架概念:ORM(对象关系映射)、MVC(模型-视图-控制器)以及IOC( inversion of control,控制反转)。我们将探讨这些概念的基本原理,以及如何动手实现这些框架。 首先,让我们来深入...

    自己的IoC框架实现

    在本项目中,我们将根据Spring的IoC原理,尝试实现自己的IoC框架。 首先,理解IoC的概念至关重要。IoC是指应用程序的控制权由传统的方式(如:对象直接创建和管理依赖关系)转移到框架或容器中,这样对象不再负责...

    IOC框架详解

    【IOC框架详解】 IOC(Inversion of Control)框架是一种软件设计模式,主要目的是为了降低对象间的耦合度,实现更好的可扩展性和可维护性。在传统的面向对象编程中,对象通常自行创建和管理它们所依赖的其他对象,...

    多种IOC框架的比较

    ### 多种IOC框架的比较 #### 概述 在软件开发领域,特别是.NET平台下,依赖注入(Inversion of Control, IOC)容器是管理对象生命周期和服务定位的关键工具。本文将对比分析几种主流的.NET IOC框架:Spring.NET、...

    仿 Spring 手写 IoC、AOP 框架.rar

    本教程将带你深入理解这两个概念,并通过手写一个简易的IoC和AOP框架来加深理解。 **依赖注入(IoC)** 依赖注入是Spring的核心特性之一,它允许开发者将对象的创建和管理权交给框架,从而降低组件之间的耦合度。在...

    C#实现的IOC和AOP框架,供学习

    学习这个框架,开发者可以深入理解IOC和AOP的概念,掌握如何在C#中实现和使用这两种模式,提升自己的编程技巧和软件设计能力。同时,了解和使用开源框架,也有助于扩展视野,了解业界最佳实践。

    简单的ioc框架, just a simple

    2. **依赖注入**:这是IOC的主要实现方式,它允许我们在运行时将依赖关系注入到对象中,而不是在编译时硬编码。依赖注入有两种主要形式:构造函数注入、setter方法注入。通过这两种方式,对象可以在不自行创建依赖的...

    Spring框架系列(7) - Spring IOC实现原理详解之IOC初始化流程.doc

    Spring 框架系列(7)- Spring IOC 实现原理详解之 IOC 初始化流程 本文将详细解释 Spring 框架中的 IOC(Inversion of Control,控制反转)实现原理之 IOC 初始化流程。IOC 是一种软件设计模式,用于将软件系统中...

    Android进阶——框架打造之IOC框架

    Android进阶——框架打造之IOC框架 实现通过Id找到控件的功能 实现通过Id找到Color、String资源 实现绑定view的点击事件、长按事件 实现绑定SetContentView 实现绑定网络的检测功能

    spring_ioc框架学习文档

    ### Spring IOC框架学习知识点 #### 一、Spring IOC框架简介 Spring框架是一个开源的企业级Java应用框架,它提供了丰富的功能来简化企业应用开发。其中,Inversion of Control (IoC)容器是Spring的核心特性之一,...

    自己做的小型IOC框架

    自己做的一个小型的IOC框架,希望大家一起研究下

    Spring Actionscript IOC 框架与 Flex Cairngorm MVC 应用开发

    在开发 Flex 应用程序时,Spring Actionscript IOC 框架和 Cairngorm MVC 模式结合使用,可以显著提升代码的可维护性和可扩展性。Spring Actionscript 是一个针对 Actionscript3 设计的轻量级框架,其灵感来源于 ...

    Flex IOC 框架概览PDF完整版及配套源码

    Flex IOC(Inversion of Control)框架是用于构建可扩展且松耦合的ActionScript和Flex应用程序的工具。IOC,也称为依赖注入,是一种设计模式,它允许组件之间的依赖关系在运行时被管理,而不是在代码中硬编码。这种...

    利用Castle框架中IOC技术

    【 Castle 框架与 IOC 技术详解】 Castle框架是一个针对.NET平台的开源软件开发框架,它集合了多种成熟的应用技术,如ActiveRecord、AspectSharp、MonoRail以及MicroKernel/Windsor等。其中,MicroKernel是Castle的...

    关于spring框架中的ioc的幽默解释.

    关于Spring框架中的IoC(控制反转)概念,我们可以通过一个幽默的例子来深入理解其核心思想。在编程领域,特别是面向对象编程中,控制反转(IoC)是一种设计原则,用于减少代码之间的耦合度,提高代码的可读性和可...

    自己写了三个分别关于WEB,IOC,ORM的框架现将开源

    自己写了三个分别关于WEB,IOC,ORM的框架现将全部开源,内有说明文档,测试示例项目,框架源代码文件,sql语句等

    轻量级IOC框架BeanContext

    轻量级的IOC框架,用于取代Spring在j2se项目中进行使用。

    Android 进阶 教你打造 Android 中的 IOC 框架 (下)

    在Android开发中,IOC(Inversion of Control,控制反转)框架是提高代码可维护性和可扩展性的重要工具。本教程的下篇将深入探讨如何构建一个Android中的IOC框架,主要涉及的技术点包括依赖注入、注解处理以及反射...

    动手写框架,模拟简易的SpringIOC.rar

    标题 "动手写框架,模拟简易的Spring IOC" 暗示了这个压缩包包含了一个教程或实践项目,目的是帮助我们理解Spring框架的核心组件——控制反转(Inversion of Control,简称IOC)。Spring框架是Java开发中广泛使用的...

Global site tag (gtag.js) - Google Analytics