mini-spring(简易版spring学习记录)(3)resourceLoder与ApplicationEventPublisher

73 阅读2分钟

image.png 这是ApplicationContext的继承结构,我们可以发现ApplicationContext主要继承了三大重要接口:分别是beanFactory,resourceLoder,ApplicationEventPublisher,上两节讲了beanfactory,在这一节我想说一下resourceLoder与ApplicationEventPublisher,

resourceLoder

我们首先看一下它的顶级接口defaultResourceLoader

@Override  
public Resource getResource(String location) {  
if(location.startsWith(CLASSPATH_URL_PREFIX)){  
return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()));  
}else {  
try{  
URL url=new URL(location);  
return new URLResource(url);  
} catch (MalformedURLException e) {  
return new FileSystemResource(location);  
}  
}  
}

它可以解析三种不同的文件地址并将其转化为Resource,所解析的resource文件最终被resourceReader解析

image.png

public void loadBeanDefinitions(Resource resource) throws BeansException {  
try {  
InputStream inputStream=resource.getInputStream();  
try {  
doLoadBeanDefinitions(inputStream);  
}finally {  
inputStream.close();  
}  
} catch (IOException | DocumentException e) {  
throw new BeansException("IOException parsing XML document from " + resource, e);  
}  
  
}  
  
private void doLoadBeanDefinitions(InputStream inputStream) throws DocumentException {  
SAXReader reader=new SAXReader();  
Document document=reader.read(inputStream);  
  
Element root=document.getRootElement();  
  
Element componentScan =root.element(COMPONENT_SCAN_ELEMENT);  
if(componentScan!=null){  
String scanPath=componentScan.attributeValue(BASE_PACKAGE_ATTRIBUTE);  
if (StrUtil.isEmpty(scanPath)){  
throw new BeansException("The value of base-package attribute can not be empty or null");  
}  
scanPackage(scanPath);  
}  
  
List<Element>beanList=root.elements(BEAN_ELEMENT);  
for(Element bean:beanList){  
String beanId = bean.attributeValue(ID_ATTRIBUTE);  
String beanName = bean.attributeValue(NAME_ATTRIBUTE);  
String className = bean.attributeValue(CLASS_ATTRIBUTE);  
String initMethodName = bean.attributeValue(INIT_METHOD_ATTRIBUTE);  
String destroyMethodName = bean.attributeValue(DESTROY_METHOD_ATTRIBUTE);  
String beanScope = bean.attributeValue(SCOPE_ATTRIBUTE);  
String lazyInit = bean.attributeValue(LAZYINIT_ATTRIBUTE);  
Class<?> clazz;  
  
try {  
clazz =Class.forName(className);  
} catch (ClassNotFoundException e) {  
throw new RuntimeException(e);  
}  
beanName=StrUtil.isEmpty(beanId)?beanName:beanId;  
if(StrUtil.isEmpty(beanName)){  
beanName=StrUtil.lowerFirst(clazz.getSimpleName());  
}  
BeanDefinition beanDefinition=new BeanDefinition(clazz);  
beanDefinition.setInitMethodName(initMethodName);  
beanDefinition.setDestroyMethodName(destroyMethodName);  
beanDefinition.setLazyInit(Boolean.parseBoolean(lazyInit));  
if (StrUtil.isNotEmpty(beanScope)) {  
beanDefinition.setScope(beanScope);  
}  
List<Element>propertyList=bean.elements(PROPERTY_ELEMENT);  
for(Element property: propertyList){  
String propertyNameAttribute=property.attributeValue(NAME_ATTRIBUTE);  
String propertyValueAttribute=property.attributeValue(VALUE_ATTRIBUTE);  
String propertyRefAttribute=property.attributeValue(REF_ATTRIBUTE);  
  
if(StrUtil.isEmpty(propertyNameAttribute)){  
throw new BeansException("The name attribute cannot be null");  
  
}  
Object value=propertyValueAttribute;  
if (StrUtil.isNotEmpty(propertyRefAttribute)) {  
value = new BeanReference(propertyRefAttribute);  
}  
beanDefinition.getPropertyValues().addPropertyValue(new PropertyValue(propertyNameAttribute,value));  
  
}  
if(getRegistry().containsBeanDefinition(beanName)){  
throw new BeansException("Duplicate beanName[" + beanName + "] is not allowed");  
}  
getRegistry().registerBeanDefinition(beanName,beanDefinition);  
}  
}

我们可以看到,它里面组合了BeanDefinitionRegister,ResourceLoader,可以将文件(特别是xml文件来解析成BeanDefinition)(通过Document树实现逐层解析的)。

ApplicationEventPublisher

这是spring实现消息传递的方式,首先有一个消息多发者

image.png

@Override  
public void multicastEvent(ApplicationEvent event) {  
for(ApplicationListener<ApplicationEvent>applicationListener:applicationListeners){  
if(supportsEvent(applicationListener,event)){  
applicationListener.onApplicationEvent(event);  
}  
}  
}  
  
private boolean supportsEvent(ApplicationListener<ApplicationEvent> applicationListener, ApplicationEvent event) {  
Type type =applicationListener.getClass().getGenericInterfaces()[0];  
Type actualTypeArgument = ((ParameterizedType) type).getActualTypeArguments()[0];  
String typeName = actualTypeArgument.getTypeName();  
Class<?>eventClassName;  
try {  
eventClassName =Class.forName(typeName);  
}catch (ClassNotFoundException e){  
throw new BeansException("wrong event class name: " + typeName);  
}  
  
return eventClassName.isAssignableFrom(event.getClass());  
  
}

每当受到一个event,它都会遍历beanFactory里的applicationListeners,通过反射来看这ApplicationListener里的event泛型(一定要继承ApplicationEvent)是否是接收到的event类或其父类,如果是,就通过钩子方法来调用applicationListener.onApplicationEvent(event);