上篇中主要使用配置文件来定义一些类实例之间的组织关系,这篇所要做的就是将其扩展,实现支持自定义化的注解,也就是使用注解来完成配置类实例之间的组织关系。废话不多,请看配置文件:
<?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()); } }
相关推荐
springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC...
自己动手做框架——ORM,MVC,IOC框架及整合视频教程 源码
根据Spring的IoC原理,实现自己的IoC框架。
IOC框架详解,很好的IOC的参考资料,相信介绍了IOC框架
对多种IOC框架进行比较,对各自的优缺点进行描述
spring_ioc框架学习文档
Android进阶——框架打造之IOC框架 实现通过Id找到控件的功能 实现通过Id找到Color、String资源 实现绑定view的点击事件、长按事件 实现绑定SetContentView 实现绑定网络的检测功能
C#实现的IOC和AOP框架,供学习
自己做的一个小型的IOC框架,希望大家一起研究下
1、Flex IOC 框架概览PDF完整版 2、Flex IOC 框架概览配套源码 3、IoC容器和Dependency Injection模式中文版
Spring框架系列(7) - Spring IOC实现原理详解之IOC初始化流程.doc
自己写了三个分别关于WEB,IOC,ORM的框架现将全部开源,内有说明文档,测试示例项目,框架源代码文件,sql语句等
轻量级的IOC框架,用于取代Spring在j2se项目中进行使用。
《仿 Spring 手写 IoC、AOP 框架》博客附件。 博客地址:https://blog.csdn.net/Supreme_Sir/article/details/109100886
简单的ioc框架, just a simple
利用Castle框架中IOC技术的技术文档
Spring框架-IoC实现CRUD
手写spring框架ioc+aop+mvc
spring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demo...
自己搭建轻量级javaWeb框架之mvc以及ioc