概述
创建不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象的模式叫工厂模式,结合以前学的反射来对依赖注入做个简单的探究
大体思路是有一个实体BeanDefinition记录类的信息,而XmlBeanConfigParser负责解析xml文件,并将实体信息传给BeansFactory,BeansFactory根据实体信息创建相应的对象,如图
demo
ClassPathXmlApplication类:
public class ClassPathXmlApplication {private BeansFactory beansFactory;private XmlBeanConfigParser beanConfigParser;public ClassPathXmlApplication(String config){this.beansFactory &#61; new BeansFactory();this.beanConfigParser &#61; new XmlBeanConfigParser();loadBeanDefinition(config);}private void loadBeanDefinition(String config) {InputStream in &#61; null;try {in &#61; this.getClass().getResourceAsStream("/"&#43;config);if (in &#61;&#61; null){throw new RuntimeException("can not find config file:"&#43;config);}List<BeanDefinition> beanDefinitions &#61; beanConfigParser.parse(in);beansFactory.addBeanDefinitions(beanDefinitions);} catch (DocumentException e) {e.printStackTrace();}finally {if (in!&#61;null){try {in.close();} catch (IOException e) {e.printStackTrace();}}}}public Object getBean(String beanId){return beansFactory.getBean(beanId);}public static void main(String[] args) {ClassPathXmlApplication xmlApplication &#61; new ClassPathXmlApplication("beans.xml");Person person &#61; (Person) xmlApplication.getBean("person");System.out.println(person);}}
XmlBeanConfigParser 类:解析xml配置文件&#xff0c;生成BeanDefinition的List传给BeanFactory
public class XmlBeanConfigParser {public List<BeanDefinition> parse(InputStream inputStream) throws DocumentException {List<BeanDefinition> beanDefinitions &#61; new ArrayList<>();SAXReader reader &#61; new SAXReader();;Document document &#61; reader.read(inputStream);Element root &#61; document.getRootElement();Iterator<Element> it&#61;root.elementIterator("bean");while (it.hasNext()){BeanDefinition beanDefinition &#61; new BeanDefinition();Element child &#61; it.next();Iterator<Attribute> attribute &#61; child.attributeIterator();while(attribute.hasNext()) {Attribute attr &#61; attribute.next();if ("id".equalsIgnoreCase(attr.getName())){beanDefinition.setId(attr.getValue());}if ("class".equalsIgnoreCase(attr.getName())){beanDefinition.setClassName(attr.getValue());}}beanDefinitions.add(beanDefinition);}return beanDefinitions;}}
BeansFactory:把解析过来的
List<BeanDefinition> beanDefinitionList
存到一个Map对象中&#xff0c;需要的时候从Map中拿
public class BeansFactory {private ConcurrentHashMap<String, BeanDefinition> beanDefinitions &#61; new ConcurrentHashMap<>();public void addBeanDefinitions(List<BeanDefinition> beanDefinitionList){for (BeanDefinition bean:beanDefinitionList) {this.beanDefinitions.put(bean.getId(),bean);}}public Object getBean(String beanId){BeanDefinition beanDefinition &#61; beanDefinitions.get(beanId);if (beanDefinition&#61;&#61;null){throw new NoSuchBeanDefinitionException("没有这个bean类");}return createBean(beanDefinition);
}private Object createBean(BeanDefinition beanDefinition) {Object bean &#61; null;try {Class beanClass &#61; Class.forName(beanDefinition.getClassName());bean &#61; beanClass.newInstance();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();}return bean;}
}
BeanDefinition:保存xml中bean对象的信息
public class BeanDefinition {private String id;private String className;public void setId(String id) {this.id &#61; id;}public void setClassName(String className) {this.className &#61; className;}public String getId() {return id;}public String getClassName() {return className;}
}
测试一下: