您的位置:首页 > 编程语言 > Java开发

【Spring源码解析】—— 简单工厂模式的BeanFactory的超简版实现

2019-05-27 23:50 1591 查看

 一、什么是简单工厂模式

设计模式的核心是“分工”,通过分工将对象与职责划分的更细化,进而提升系统设计的可扩展性,使其更容易维护。

 

开闭原则:对扩展开放,对修改关闭;要增加一个新的处理逻辑,可以开一个新的类,不要在老的上面修改

依赖倒转原则:依赖关系从具体转向抽象,也就是说:A调用B,不是直接调用B的实现,而是依赖B的接口

迪米特法则:类尽量少的与其他类发生关系,或者产生依赖,以此来使扩展可以更容易

 

工厂模式中的三种:简单工厂模式、工厂方法模式、抽象工厂模式;实现了创建者和调用者的分离,调用者不需要知道具体的创建者是什么类,只需要知道工厂的接口以及自己想要的产品名称,就可以进行调用得到想要的产品

简单工厂模式:简单工厂模式也称为静态工厂模式,工厂类一般采用静态方法,根据接收的参数不同来确定返回对象实例,但简单工厂模式违反了开闭原则,要增加一个新的类别必须要修改代码

注意,简单工厂模式就是:针对一个项目或者一个独立模块只有一个工厂类,而工厂方法模式是有一组实现了相同接口的工厂类(虽然符合开闭原则,但是会增加新的类来扩展,看情况而定,实际上在项目开发中通常还是用简单工厂比较多)

二、依据Spring中的BeanFactory自己实现简版

首先是,先写一个接口类,BeanFactory的接口类如下:

public interface BeanFactory {
    Object getBean(String beanName);
}

下面是xml配置文件 springtest.xml:

<?xml version="1.0" encoding="UTF-8"?>

<beans>

<bean id="usertest" class="beanfactory.demo.User">

<property name="username" value="lxlx" />

<property name="passWord" value="111" />

<property name="age" value="11"/>

</bean>

</beans>

下面是bean定义的class文件 User类:

public class User {
private String username;
private String passWord;
private int age;

public void setUsername(String username) {
this.username = username;
}
public void setPassWord(String passWord) { this.passWord = passWord; } public void setAge(int age) { this.age = age; } public String getUsername() { return username; } public String getPassWord() { return passWord; } public int getAge() { return age; } }

接下来是实现类 ConcreteBeanFactory:

package beanfactory.demo;

import org.dom4j.io.SAXReader;

import org.dom4j.*;

import java.io.File;

import java.lang.reflect.Type;

import java.util.HashMap;

import java.util.Map;

import java.util.Iterator;

import java.lang.reflect.Method;

/**

* Created by xiami on 2019/5/26.

*/

public class ConcreteBeanFactory implements BeanFactory{

private Map<String, Object> beanDefinitionMap = new HashMap<String, Object>();

//简单工厂模式的特征是:一个工厂中可以生产多种不同的产品,这里的Bean其实是没有区分不同的bean,是可以通过get返回不同的bean

@Override

public Object getBean(String beanName) {

return beanDefinitionMap.get(beanName);

}

//增加一个init的操作方法

//从xml配置文件中进行解析读取

public void init(String xmlPath){

SAXReader saxReader = new SAXReader();

File file = new File(xmlPath);

try {

Document document = saxReader.read(file);

Element root = document.getRootElement();

Element foo;

// 遍历bean

for (Iterator i = root.elementIterator("bean"); i.hasNext();) {

foo = (Element) i.next();

// 获取bean的属性id和class

Attribute id = foo.attribute("id");

Attribute cls = foo.attribute("class");

// 利用Java反射机制,通过class的名称获取Class对象

Class<?> bean = Class.forName(cls.getText());

// 获取对应class的信息

java.beans.BeanInfo info = java.beans.Introspector.getBeanInfo(bean);

// 获取其属性描述

java.beans.PropertyDescriptor pd[] = info.getPropertyDescriptors();

// 设置值的方法

Method mSet = null;

// 创建一个对象

Object obj = bean.newInstance();

// 遍历该bean的property属性

for (Iterator ite = foo.elementIterator("property"); ite.hasNext();) {

Element foo2 = (Element) ite.next();

// 获取该property的name属性

Attribute name = foo2.attribute("name");

String value = null;

Object typeValue = null;

//获取value值

value = foo2.attributeValue("value");

for (int k = 0; k < pd.length; k++) {

if (pd[k].getName().equalsIgnoreCase(name.getText())) {

mSet = pd[k].getWriteMethod();

//设置值这里,需要根据类型给value做类型转换

//properties中包含了properType的项,因为当前程序中就只有String和Int,先处理这样的类型

Type mType = pd[k].getPropertyType();

if (mType.getTypeName().equals("java.lang.String")){

typeValue = String.valueOf(value);

}

else if(mType.getTypeName().equals("int")){

typeValue = Integer.parseInt(value);

}

mSet.invoke(obj, typeValue);

}

}

}

// 将对象放入beanMap中,其中key为id值,value为对象

beanDefinitionMap.put(id.getText(), obj);

}

}catch (Exception e){

System.out.println(e.toString());

}

}

}

 

下面是测试类:

public class Client {

public static void main(String[] args){

AbstractBeanFactory absbf = new AbstractBeanFactory();

absbf.init("E:\\java-demo\\src\\beanfactory\\demo\\springtest.xml");

User user = (User)absbf.getBean("usertest");

System.out.println("User类的bean有没有创建成功:" + user);

System.out.println("属性值:" + user.getUsername() + "," + user.getPassWord() + "," + user.getAge());

}

}

测试结果是:

 

要理解的是:简单工厂模式是一种思想,就是:不针对特定的产品进行工厂的划分,也就是说没有多个批次或者类别的工厂,而是所有的内容都在一个工厂里面生产,你需要什么我给你什么即可

 

参考文章:https://blog.csdn.net/mlc1218559742/article/details/52776160/

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐