【Spring源码解析】—— 简单工厂模式的BeanFactory的超简版实现
一、什么是简单工厂模式
设计模式的核心是“分工”,通过分工将对象与职责划分的更细化,进而提升系统设计的可扩展性,使其更容易维护。
开闭原则:对扩展开放,对修改关闭;要增加一个新的处理逻辑,可以开一个新的类,不要在老的上面修改
依赖倒转原则:依赖关系从具体转向抽象,也就是说: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/
【Spring源码解析】—— 简单工厂模式的BeanFactory的超简版实现的更多相关文章
- spring源码解析——2容器的基本实现(第2版笔记)
感觉第二版写的略潦草,就是在第一版的基础上加上了新的流行特性,比如idea,springboot,但是,潦草痕迹遍布字里行间. 虽然换成了idea,但是很多截图还是eclipse的,如果不是看了第一版 ...
- 【Spring源码解析】—— 委派模式的理解和使用
一.什么是委派模式 委派模式,是指什么呢?从字面含义理解,委派就是委托安排的意思,委派模式就是在做具体某件事情的过程中,交给其他人来做,这个事件就是在我的完整链路上的一部分,但是复杂度较高的情况下或者 ...
- 【Spring源码解析】—— 策略模式在Spring中的应用
一. 什么是策略模式 策略模式的定义/含义:策略本身就是为了实现某一个目标而采取的一种工作方式,因此只要能够达成目标,则采取哪一种策略都可以:因此多种实际的策略之间是相互平行的. 注意 ...
- Spring源码解析 - AbstractBeanFactory 实现接口与父类分析
我们先来看类图吧: 除了BeanFactory这一支的接口,AbstractBeanFactory主要实现了AliasRegistry和SingletonBeanRegistry接口. 这边主要提供了 ...
- spring 源码解析
1. [文件] spring源码.txt ~ 15B 下载(167) ? 1 springн┤┬вио╬Ш: 2. [文件] spring源码分析之AOP.txt ~ 15KB 下载( ...
- Spring源码解析——循环依赖的解决方案
一.前言 承接<Spring源码解析--创建bean>.<Spring源码解析--创建bean的实例>,我们今天接着聊聊,循环依赖的解决方案,即创建bean的ObjectFac ...
- Spring源码解析系列汇总
相信我,你会收藏这篇文章的 本篇文章是这段时间撸出来的Spring源码解析系列文章的汇总,总共包含以下专题.喜欢的同学可以收藏起来以备不时之需 SpringIOC源码解析(上) 本篇文章搭建了IOC源 ...
- Spring源码解析之ConfigurationClassPostProcessor(二)
上一个章节,笔者向大家介绍了spring是如何来过滤配置类的,下面我们来看看在过滤出配置类后,spring是如何来解析配置类的.首先过滤出来的配置类会存放在configCandidates列表, 在代 ...
- Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean
Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean 七千字长文深刻解读,Spirng中是如何初始化单例bean的,和面试中最常问的Sprin ...
随机推荐
- HDOJ 2120 Ice_cream's world I
Ice_cream's world I ice_cream's world is a rich country, it has many fertile lands. Today, the queen ...
- 4、python中的布尔值和None
一.布尔值 1.布尔值只有两个:True.Flase,表示python语句的真与假: 2.在python早期的版本,布尔值用1和0表示. 二.None 1.None表示虚无,什么也没有: 2.千万不要 ...
- laravel5.2总结--redis使用
一切的前提都是已经安装好了redis服务器,并且能启动(我只总结了mac的安装方法:传送门) 我自己使用的是mac系统,有个教程可以参考下,传送门: 1.安装PHP PRedis 1>PRedi ...
- Hyper-v Server 2012 R2增强会话模式
从Windows Server 2012 R2开始,通过使用Hyper-v增强会话模式Hyper-v中的虚拟机允许重定向虚拟机连接会话中的本地资源.这是因为Windows Server 2012 及早 ...
- leetcode 【 Merge k Sorted Lists 】python 实现
题目: Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexit ...
- 【Remove Nth Node From End of List】cpp
题目: Given a linked list, remove the nth node from the end of list and return its head. For example, ...
- hibernate 出错 集合
Lazy="false"反而出错 错误信息: “System.Configuration.ConfigurationErrorsException”类型的异常在 Spring.Co ...
- linux简单授权
linux授权:r: readw: writex:executech:change b=byte1byte=8 bitsu=user ownerg=groupo=othera=all_ _ _ _ _ ...
- APP网络测试点
- SQLAlchemy 学习笔记(三):ORM 中的关系构建
个人笔记,不保证正确. 关系构建:ForeignKey 与 relationship 关系构建的重点,在于搞清楚这两个函数的用法.ForeignKey 的用法已经在 SQL表达式语言 - 表定义中的约 ...