- 前言(本文为原创,转载请注明出处)
个人之前对于框架的学习,就停留在配置,使用阶段。说实话过段时间就会忘得荡然无存。也不知道框架的运行逻辑,就是知道添加个注解,就可以用了。
由于实习,时间比较多,也感恩遇到个好老师,教并给我时间看源码,虽然没有做过多少业务,但是感觉比做业务更有意义。慢慢的去跟代码, 对Spring
运行流程大致有个解。现分享给大家,不足之处,希望各位补充,相互学习。
- 从源码看Spring
可能我们很少在意,ClassPathXmlApplicationContext这个类,其实这个类做了很多的事情,它才是我们了解Spring框架的窗户。
ClassPathXmlApplicationContext c=new ClassPathXmlApplicationContext("ApplicationContext.xml");
当我们执行上面的语句的时候, public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
super(parent); setConfigLocations(configLocations); if (refresh) { refresh(); } } 实际上走的是这个构造函数,这个构造函数做了两个事情,一是setConfigLocations()方法初始化一些配置。一是reFresh()函数,该函数进行了Bean的注册,事件广播等。 refresh()函数十分重要,具体干了什么,请看下面的源码注释: public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // 注册Bean. invokeBeanFactoryPostProcessors(beanFactory); // 登记拦截bean创建的处理器 registerBeanPostProcessors(beanFactory); initMessageSource(); // 创建了一个广播事件的类 initApplicationEventMulticaster(); onRefresh(); // 注册事件监听者 registerListeners(); // 实例化那些被配置成单例的Bean finishBeanFactoryInitialization(beanFactory); // 结束刷新,实际上就是广播事件等操作 finishRefresh(); } catch (BeansException ex) { // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset ‘active‘ flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } } } 先对Spring框架的事件机制简单的做个扩展,常规来看事件涉及如下几方: 1)事件本身(生产者) 2)消费事件者 3)事件管理(订阅中心) 1.Spring事件本身从ApplicationEvent派生,事件消费者为ApplicationListener<T extends ApplicationEvent>,事件管理中心为ApplicationEventMulticaster 它负责管理监听者等。 2.Spring当广播一个事件时,它首先去查找该事件的监听者,然后再去遍历监听者调用其onApplicationEvent(Application evnet)接口,将事件传给监听者。 最后当我们调用getBean()的时候,实际上经过refresh()的bean注册,已经被缓存到map里面,直接出map里面取出实例化即可。
- 代码简易实现Spring
上面的工程目录结构为com.springImpl.annotion放的spring的注解类。com.springImple.core放得实现Spring框架的核心类。com.springImpl.test放的是测试类。
1)注解类:
假设现在我这个框架还是比较搓,就一个注解,
import java.lang.annotation.*; @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD)//为了书写简单 这里只作用于属性 也就是域 成员变量 public @interface Resources { }
2)事件类:
现在这个事件就是一个约定,实际啥也没有
public class ApplicationEvent { }
3)监听者类
public interface ApplicationListener<T extends ApplicationEvent> { void onApplicationEvent(T event); }
4)事件订阅中心类
public interface ApplicationEventMulticaster { void publishEvent(ApplicationEvent event); }
5)解析配置文件的类
import com.springImpl.annotion.Resources; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import java.io.*; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Iterator; public class ConfigResolver extends ApplicationEvent implements ApplicationEventMulticaster{ private String configXml="spring.xml"; static HashMap<String ,Object> BeanFactory;//这里就是模仿beanFactory 将所有的bean用beanid与对应实例用map保存起来 static HashMap<String ,ApplicationListener> RegistryListener;//这里保存那些是监听者的bean static { BeanFactory=new HashMap<>(); RegistryListener=new HashMap<>(); } public ConfigResolver(String config){ configXml=config==null?configXml:config;//默认就是spring.xml setConfigLocations(configXml); refresh(); } public Object getBean(String beanId){ return BeanFactory.get(beanId); } private void setConfigLocations(String configXml){ //什么都不做 当然可以做一些环境的检查 将配置的提取用一个类去处理等等 我这偷个懒 } private void refresh(){ //注册bean invokeBeanFactoryPostProcessors(BeanFactory); //登记监听者 registerListeners(); //j结束刷新 表面程序已经启动 可以广播这个刷新完毕事件了 广播事件 finishRefresh(); } private void finishRefresh(){ publishEvent(this); } /** * 从beanfactory找到那些是监听者类型的bean */ private void registerListeners(){ Iterator<String> it=BeanFactory.keySet().iterator(); while(it.hasNext()){ String key=it.next(); if(BeanFactory.get(key) instanceof ApplicationListener){ RegistryListener.put(key,(ApplicationListener)BeanFactory.get(key)); it.remove(); } } } /** * 将配置文件中的bean全部实例化到map里面 * @param beanFactory */ private void invokeBeanFactoryPostProcessors(HashMap beanFactory){ InputStream in= null; try { in = ConfigResolver.class.getResourceAsStream(configXml)==null? new FileInputStream(configXml):ConfigResolver.class.getResourceAsStream(configXml);//兼容资源路径 与 绝对路径 } catch (FileNotFoundException e) { e.printStackTrace(); } try { DocumentBuilder db=DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document dc=db.parse(in); NodeList nl=dc.getElementsByTagName("bean"); for(int i=0;i<nl.getLength();i++){ NamedNodeMap attrs= nl.item(i).getAttributes(); HashMap<String,String> beanMap=new HashMap<>();//对应一个bean标签 for(int j=0;j<attrs.getLength();j++){ String beanIdName=attrs.item(j).getNodeName();//假装这个节点Id String beanId=null; if(beanIdName!=null) { beanId = attrs.item(j).getNodeValue(); } if(beanId!=null){ beanMap.put(beanIdName,beanId); } String beanClassName=attrs.item(j).getNodeName();//假装这个节点就是class String beanClass=null; if(beanClassName!=null) { beanClass = attrs.item(j).getNodeValue(); } if(beanClass!=null){ beanMap.put(beanClassName,beanClass); } } String beanId=beanMap.get("id"); String beanClass=beanMap.get("class"); if(beanClass==null||beanId==null){ continue; } try { Class cls=Class.forName(beanClass); Object beanObject=cls.newInstance(); Field[] fds=beanObject.getClass().getDeclaredFields(); for(Field fd:fds){ fd.setAccessible(true);//获取访问私有变量权限 Resources rs=fd.getAnnotation(Resources.class); if(rs!=null){ fd.set(beanObject,fd.getType().newInstance());//实例化带有Resource注解的成员 } } beanFactory.put(beanId,beanObject);//将bean放到map } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } } } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * 广播事件 * @param event */ @Override public void publishEvent(ApplicationEvent event) { Iterator<String> it=RegistryListener.keySet().iterator(); while(it.hasNext()){ RegistryListener.get(it.next()).onApplicationEvent(event); } } } 6)看一下测试类: //监听程序启动的类 监听者
public class ApplicationStartLister implements ApplicationListener<ApplicationEvent> { @Override public void onApplicationEvent(ApplicationEvent event) { System.out.println("SpringImpl App start"); } } //假设这里有个眼瞎的人 他用注解注注入了个眼睛Ege类
public class Blind { @Resources private Ege ege; public Ege getEge(){ return ege; } }
//眼睛Ege类
public class Ege { public String see(){ return "the world is so beautiful."; } } //主程序
public class DoMain {
public static void main(String []args){ ConfigResolver cfg=new ConfigResolver("E:\\__Java\\__idea_proj\\SpringImpl\\src\\resources\\spring.xml"); Blind b= (Blind) cfg.getBean("mybean"); System.out.println("tell me how is the world :"+b.getEge().see()); } }
//配置文件
7)运行结果
到此完毕,一个简单的模仿spring框架完毕。
时间: 2024-10-24 08:13:07