赞
踩
接上篇文章中实现了通过beanFactory注册beanDefinition, 通过上层父类生成bean的实例同时可以调用有参构造创建bean实例,本章主要实现注入属性和依赖对象;以xml方式配置bean并注入
定义属性对象值.
public class PropertyValue {
private final String name;
private final Object value;
public PropertyValue(String name, Object value) {
this.name = name;
this.value = value;
}
// get set方法
}
属性对象的整合
public class PropertyValues { private final List<PropertyValue> propertyValueList = new ArrayList<>(); public void addPropertyValue(PropertyValue pv){ this.propertyValueList.add(pv); } public List<PropertyValue> getPropertyValues() { return propertyValueList; } public PropertyValue getPropertyValue(String propertyName){ for (PropertyValue pv : this.propertyValueList) { if(pv.getName().equals(propertyName)){ return pv; } } return null; } }
public class BeanReference {
private final String beanName;
public BeanReference(String beanName) {
this.beanName = beanName;
}
public String getBeanName() {
return beanName;
}
}
有了对象属性值之后下一步就是优化BeanDefinition为其添加属性值字段
public class BeanDefinition {
private Class beanClass;
private PropertyValues propertyValues;
public BeanDefinition(Class beanClass){
this.beanClass = beanClass;
this.propertyValues = new PropertyValues();
}
public BeanDefinition(Class beanClass,PropertyValues propertyValues){
this.beanClass = beanClass;
this.propertyValues = propertyValues != null ? propertyValues : new PropertyValues();
}
}
因为我们就可以在创建bean时为字段注入值
其中applyPropertyValues用于从beanDefinition中读取属性的配置信息然后通过BeanUtil(hutool-all中提供的类)为其赋值
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory { private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy(); @Override protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException { Object bean = null; try { bean = createBeanInstance(beanDefinition,beanName,args); applyPropertyValues(beanName,bean,beanDefinition); }catch (Exception e){ e.printStackTrace(); } addSingleton(beanName,bean); return bean; } // 创建bean实例 protected Object createBeanInstance(BeanDefinition beanDefinition, String beanName, Object[] args) throws InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException { Constructor constructorToUse = null; Class<?> beanClass = beanDefinition.getBeanClass(); Constructor<?>[] declaredConstructors = beanClass.getDeclaredConstructors(); for (Constructor ctor : declaredConstructors) { if (null != args && ctor.getParameterTypes().length == args.length) { constructorToUse = ctor; break; } } return instantiationStrategy.instantiate(beanDefinition, beanName, constructorToUse, args); } // 设置属性值 protected void applyPropertyValues(String beanName, Object bean, BeanDefinition beanDefinition){ try { // 从beanDefinition中获取property PropertyValues propertyValues = beanDefinition.getPropertyValues(); for (PropertyValue propertyValue : propertyValues.getPropertyValues()) { String name = propertyValue.getName(); Object value = propertyValue.getValue(); if(value instanceof BeanReference){ BeanReference beanReference = (BeanReference) value; value = getBean(beanReference.getBeanName()); } BeanUtil.setFieldValue(bean,name,value); } }catch (Exception e){ throw new BeansException("Error setting property values" + beanName); } } }
@Test public void test_BeanFactory() { // 1.初始化 BeanFactory DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); // 2. UserDao 注册 beanFactory.registerBeanDefinition("userDao", new BeanDefinition(UserDao.class)); // 3. UserService 设置属性[uId、userDao] PropertyValues propertyValues = new PropertyValues(); propertyValues.addPropertyValue(new PropertyValue("uId", "10001")); propertyValues.addPropertyValue(new PropertyValue("userDao",new BeanReference("userDao"))); // 4. UserService 注入bean BeanDefinition beanDefinition = new BeanDefinition(UserService.class, propertyValues); beanFactory.registerBeanDefinition("userService", beanDefinition); // 5. UserService 获取bean UserService userService = (UserService) beanFactory.getBean("userService"); userService.queryUserInfo(); }
通过Resource获取文件流
public interface Resource {
InputStream getInputStream() throws IOException;
}
通过path读取文件
public class ClassPathResource implements Resource{ private final String path; private ClassLoader classLoader; public ClassPathResource(String path){ this(path,(ClassLoader) null); } public ClassPathResource(String path, ClassLoader classLoader) { Assert.notNull(path, "Path must not be null"); this.path = path; this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader()); } @Override public InputStream getInputStream() throws IOException { InputStream is = classLoader.getResourceAsStream(path); if(is == null){ throw new FileNotFoundException( this.path + " cannot be opened because it does not exist" ); } return is; } }
public class FileSystemResource implements Resource{
private final File file;
private final String path;
public FileSystemResource(String path) {
this.file = new File(path);
this.path = path;
}
@Override
public InputStream getInputStream() throws IOException {
return new FileInputStream(this.file);
}
public String getPath() {
return path;
}
}
public class UrlResource implements Resource{ private final URL url; public UrlResource(URL url) { Assert.notNull(url,"URL must not be null"); this.url = url; } @Override public InputStream getInputStream() throws IOException { URLConnection con = this.url.openConnection(); try { return con.getInputStream(); }catch (IOException ex){ if (con instanceof HttpURLConnection){ ((HttpURLConnection) con).disconnect(); } throw ex; } } }
资源加载器,提供加载Resource的方法.
public interface ResourceLoader {
String CLASSPATH_URL_PREFIX = "classpath:";
Resource getResource(String location);
}
具体的实现类,根据你传入的location的类型来判断需要那种Resource资源加载器
public class DefaultResourceLoader implements ResourceLoader{ // 根据传入path的类型来决定使用哪个加载器进行加载获得资源流 @Override public Resource getResource(String location) { Assert.notNull(location, "Location must not be null"); 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); } } } }
bean定义读取,包括registry(DefaultListableFactory) 注册beanDefinitin到bean工厂中, resourceloader() 资源加载器
public interface BeanDefinitionReader {
BeanDefinitionRegistry getRegistry();
ResourceLoader getResourceLoader();
void loadBeanDefinitions(Resource resource) throws BeansException;
void loadBeanDefinitions(Resource... resources) throws BeansException;
void loadBeanDefinitions(String location) throws BeansException;
}
抽象类中保存了所有beanDefinitionReader通用的方法也就是接收registry和resourceLoader
public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader{ private final BeanDefinitionRegistry registry; private ResourceLoader resourceLoader; protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) { this(registry, new DefaultResourceLoader()); } public AbstractBeanDefinitionReader(BeanDefinitionRegistry registry, ResourceLoader resourceLoader) { this.registry = registry; this.resourceLoader = resourceLoader; } @Override public BeanDefinitionRegistry getRegistry() { return registry; } @Override public ResourceLoader getResourceLoader() { return resourceLoader; } }
通过解析xml文件来获得beanDefinition然后注册到beanFactory中,同时为属性进行赋值。
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader{ public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) { super(registry); } public XmlBeanDefinitionReader(BeanDefinitionRegistry registry, ResourceLoader resourceLoader) { super(registry, resourceLoader); } @Override public void loadBeanDefinitions(Resource resource) throws BeansException { try { try (InputStream inputStream = resource.getInputStream()){ doLoadBeanDefinitions(inputStream); } }catch (IOException | ClassNotFoundException e){ throw new BeansException("IOException parsing XML document from " + resource,e); } } @Override public void loadBeanDefinitions(Resource... resources) throws BeansException { for (Resource resource : resources) { loadBeanDefinitions(resource); } } @Override public void loadBeanDefinitions(String location) throws BeansException { ResourceLoader resourceLoader = getResourceLoader(); // 判断是哪种Resource. Resource resource = resourceLoader.getResource(location); loadBeanDefinitions(resource); } protected void doLoadBeanDefinitions(InputStream inputStream) throws ClassNotFoundException { Document doc = XmlUtil.readXML(inputStream); Element root = doc.getDocumentElement(); NodeList childNodes = root.getChildNodes(); for(int i=0;i<childNodes.getLength();i++){ // 判断元素 if(!(childNodes.item(i) instanceof Element)) continue; // 判断对象是否是<bean> 开头的 if(!"bean".equals(childNodes.item(i).getNodeName())) continue; // 解析标签 Element bean = (Element) childNodes.item(i); String id = bean.getAttribute("id"); String name = bean.getAttribute("name"); String className = bean.getAttribute("class"); // 获取 Class,方便获取类中的名称 Class<?> clazz = Class.forName(className); // 优先级 id > name String beanName = StrUtil.isNotEmpty(id) ? id : name; if (StrUtil.isEmpty(beanName)) { beanName = StrUtil.lowerFirst(clazz.getSimpleName()); } // 定义Bean. BeanDefinition beanDefinition = new BeanDefinition(clazz); // 读取属性并填充 for(int j=0;j<bean.getChildNodes().getLength();j++){ if (!(bean.getChildNodes().item(j) instanceof Element)) continue; if (!"property".equals(bean.getChildNodes().item(j).getNodeName())) continue; // 解析标签:property Element property = (Element) bean.getChildNodes().item(j); String attrName = property.getAttribute("name"); String attrValue = property.getAttribute("value"); String attrRef = property.getAttribute("ref"); // 获取属性值:引入对象、值对象 Object value = StrUtil.isNotEmpty(attrRef) ? new BeanReference(attrRef) : attrRef; // 创建属性信息 PropertyValue propertyValue = new PropertyValue(attrName,value); beanDefinition.getPropertyValues().addPropertyValue(propertyValue); } if(getRegistry().containsBeanDefinition(beanName)){ throw new BeansException("Duplicate beanName[" + beanName + "] is not allowed"); } getRegistry().registerBeanDefinition(beanName,beanDefinition); } } }
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="userDao" class="cn.bugstack.springframework.test.bean.UserDao"/>
<bean id="userService" class="cn.bugstack.springframework.test.bean.UserService">
<property name="uId" value="10001"/>
<property name="userDao" ref="userDao"/>
</bean>
</beans>
@Test
public void test_classpath(){
// 1.初始化 BeanFactory registry
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 2. 读取配置文件&注册Bean
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions("classpath:spring.xml");
// 3. 获取Bean对象调用方法 (beanFactory.registryBeanDefinition) getBean -> createBean -> applyProperties
UserService userService = (UserService) beanFactory.getBean("userService", UserService.class);
String result = userService.queryUserInfo();
System.out.println("测试结果: " + result);
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。