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