
如上图,设计一个软件用来进行加减计算。我们第一想法就是使用工具类,提供对应的加法和减法的工具方法。
x1//用于两个整数相加2public static int add(int a,int b){3 return a + b;4}56//用于两个整数相加7public static int add(int a,int b,int c){8 return a + b + c;9}1011//用于n个整数相加12public static int add(Integer ... arr) {13 int sum = 0;14 for (Integer i : arr) {15 sum += i;16 }17 return sum;18}上面的形式比较单一、有限,如果形式变化非常多,这就不符合要求,因为加法和减法运算,两个运算符与数值可以有无限种组合方式。比如 1+2+3+4+5、1+2+3-4等等。
显然,现在需要一种翻译识别机器,能够解析由数字以及 + - 符号构成的合法的运算序列。如果把运算符和数字都看作节点的话,能够逐个节点的进行读取解析运算,这就是解释器模式的思维。
定义:
给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。
在解释器模式中,我们需要将待解决的问题,提取出规则,抽象为一种“语言”。比如加减法运算,规则为:由数值和+-符号组成的合法序列,“1+3-2” 就是这种语言的句子。
解释器就是要解析出来语句的含义。但是如何描述规则呢?
文法(语法)规则:
文法是用于描述语言的语法结构的形式规则。
xxxxxxxxxx41expression ::= value | plus | minus2plus ::= expression ‘+’ expression3minus ::= expression ‘-’ expression4value ::= integer
注意: 这里的符号“::=”表示“定义为”的意思,竖线 | 表示或,左右的其中一个,引号内为字符本身,引号外为语法。
上面规则描述为 :
表达式可以是一个值,也可以是plus或者minus运算,而plus和minus又是由表达式结合运算符构成,值的类型为整型数。
抽象语法树:
在计算机科学中,抽象语法树(AbstractSyntaxTree,AST),或简称语法树(Syntax tree),是源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。
用树形来表示符合文法规则的句子。

解释器模式包含以下主要角色。
【例】设计实现加减法的软件

代码如下:
xxxxxxxxxx1221//抽象角色AbstractExpression2public abstract class AbstractExpression {3 public abstract int interpret(Context context);4}56//终结符表达式角色7public class Value extends AbstractExpression {8 private int value;910 public Value(int value) {11 this.value = value;12 }1314 15 public int interpret(Context context) {16 return value;17 }1819 20 public String toString() {21 return new Integer(value).toString();22 }23}2425//非终结符表达式角色 加法表达式26public class Plus extends AbstractExpression {27 private AbstractExpression left;28 private AbstractExpression right;2930 public Plus(AbstractExpression left, AbstractExpression right) {31 this.left = left;32 this.right = right;33 }3435 36 public int interpret(Context context) {37 return left.interpret(context) + right.interpret(context);38 }3940 41 public String toString() {42 return "(" + left.toString() + " + " + right.toString() + ")";43 }44}4546///非终结符表达式角色 减法表达式47public class Minus extends AbstractExpression {48 private AbstractExpression left;49 private AbstractExpression right;5051 public Minus(AbstractExpression left, AbstractExpression right) {52 this.left = left;53 this.right = right;54 }5556 57 public int interpret(Context context) {58 return left.interpret(context) - right.interpret(context);59 }6061 62 public String toString() {63 return "(" + left.toString() + " - " + right.toString() + ")";64 }65}6667//终结符表达式角色 变量表达式68public class Variable extends AbstractExpression {69 private String name;7071 public Variable(String name) {72 this.name = name;73 }7475 76 public int interpret(Context ctx) {77 return ctx.getValue(this);78 }7980 81 public String toString() {82 return name;83 }84}8586//环境类87public class Context {88 private Map<Variable, Integer> map = new HashMap<Variable, Integer>();8990 public void assign(Variable var, Integer value) {91 map.put(var, value);92 }9394 public int getValue(Variable var) {95 Integer value = map.get(var);96 return value;97 }98}99100//测试类101public class Client {102 public static void main(String[] args) {103 Context context = new Context();104105 Variable a = new Variable("a");106 Variable b = new Variable("b");107 Variable c = new Variable("c");108 Variable d = new Variable("d");109 Variable e = new Variable("e");110 //Value v = new Value(1);111112 context.assign(a, 1);113 context.assign(b, 2);114 context.assign(c, 3);115 context.assign(d, 4);116 context.assign(e, 5);117118 AbstractExpression expression = new Minus(new Plus(new Plus(new Plus(a, b), c), d), e);119120 System.out.println(expression + "= " + expression.interpret(context));121 }122}
1,优点:
易于改变和扩展文法。
由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。每一条文法规则都可以表示为一个类,因此可以方便地实现一个简单的语言。
实现文法较为容易。
在抽象语法树中每一个表达式节点类的实现方式都是相似的,这些类的代码编写都不会特别复杂。
增加新的解释表达式较为方便。
如果用户需要增加新的解释表达式只需要对应增加一个新的终结符表达式或非终结符表达式类,原有表达式类代码无须修改,符合 "开闭原则"。
2,缺点:
对于复杂文法难以维护。
在解释器模式中,每一条规则至少需要定义一个类,因此如果一个语言包含太多文法规则,类的个数将会急剧增加,导致系统难以管理和维护。
执行效率较低。
由于在解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦。
自定义spring框架前,先回顾一下spring框架的使用,从而分析spring的核心,并对核心功能进行模拟。
数据访问层。定义UserDao接口及其子实现类
xxxxxxxxxx101public interface UserDao {2 public void add();3}45public class UserDaoImpl implements UserDao {67 public void add() {8 System.out.println("userDaoImpl ....");9 }10}业务逻辑层。定义UserService接口及其子实现类
xxxxxxxxxx171public interface UserService {2 public void add();3}45public class UserServiceImpl implements UserService {67 private UserDao userDao;89 public void setUserDao(UserDao userDao) {10 this.userDao = userDao;11 }1213 public void add() {14 System.out.println("userServiceImpl ...");15 userDao.add();16 }17}定义UserController类,使用main方法模拟controller层
xxxxxxxxxx101public class UserController {2 public static void main(String[] args) {3 //创建spring容器对象4 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");5 //从IOC容器中获取UserService对象6 UserService userService = applicationContext.getBean("userService", UserService.class);7 //调用UserService对象的add方法8 userService.add();9 }10}编写配置文件。在类路径下编写一个名为ApplicationContext.xml的配置文件
xxxxxxxxxx161<?xml version="1.0" encoding="UTF-8"?>2<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"3 xmlns="http://www.springframework.org/schema/beans"4 xmlns:context="http://www.springframework.org/schema/context"5 xsi:schemaLocation="http://www.springframework.org/schema/beans6 http://www.springframework.org/schema/beans/spring-beans.xsd7 http://www.springframework.org/schema/context8 http://www.springframework.org/schema/context/spring-context.xsd">910 <bean id="userService" class="com.itheima.service.impl.UserServiceImpl">11 <property name="userDao" ref="userDao"></property>12 </bean>1314 <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"></bean>1516</beans>代码运行结果如下:

通过上面代码及结果可以看出:
上面三点体现了Spring框架的IOC(Inversion of Control)和DI(Dependency Injection, DI)
Spring大约有20个模块,由1300多个不同的文件构成。这些模块可以分为:
核心容器、AOP和设备支持、数据访问与集成、Web组件、通信报文和集成测试等,下面是 Spring 框架的总体架构图:

核心容器由 beans、core、context 和 expression(Spring Expression Language,SpEL)4个模块组成。
Spring 就是面向 Bean 的编程(BOP,Bean Oriented Programming),Bean 在 Spring 中处于核心地位。Bean对于Spring的意义就像Object对于OOP的意义一样,Spring中没有Bean也就没有Spring存在的意义。Spring IoC容器通过配置文件或者注解的方式来管理bean对象之间的依赖关系。
spring中bean用于对一个类进行封装。如下面的配置:
xxxxxxxxxx41<bean id="userService" class="com.itheima.service.impl.UserServiceImpl">2 <property name="userDao" ref="userDao"></property>3</bean>4<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"></bean>为什么Bean如此重要呢?
Spring中Bean的创建是典型的工厂模式,这一系列的Bean工厂,即IoC容器,为开发者管理对象之间的依赖关系提供了很多便利和基础服务,在Spring中有许多IoC容器的实现供用户选择,其相互关系如下图所示。

其中,BeanFactory作为最顶层的一个接口,定义了IoC容器的基本功能规范,BeanFactory有三个重要的子接口:ListableBeanFactory、HierarchicalBeanFactory和AutowireCapableBeanFactory。但是从类图中我们可以发现最终的默认实现类是DefaultListableBeanFactory,它实现了所有的接口。
那么为何要定义这么多层次的接口呢?
每个接口都有它的使用场合,主要是为了区分在Spring内部操作过程中对象的传递和转化,对对象的数据访问所做的限制。例如,
这三个接口共同定义了Bean的集合、Bean之间的关系及Bean行为。最基本的IoC容器接口是BeanFactory,来看一下它的源码:
xxxxxxxxxx261public interface BeanFactory {23 String FACTORY_BEAN_PREFIX = "&";45 //根据bean的名称获取IOC容器中的的bean对象6 Object getBean(String name) throws BeansException;7 //根据bean的名称获取IOC容器中的的bean对象,并指定获取到的bean对象的类型,这样我们使用时就不需要进行类型强转了8 <T> T getBean(String name, Class<T> requiredType) throws BeansException;9 Object getBean(String name, Object... args) throws BeansException;10 <T> T getBean(Class<T> requiredType) throws BeansException;11 <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;12 13 <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);14 <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);1516 //判断容器中是否包含指定名称的bean对象17 boolean containsBean(String name);18 //根据bean的名称判断是否是单例19 boolean isSingleton(String name) throws NoSuchBeanDefinitionException;20 boolean isPrototype(String name) throws NoSuchBeanDefinitionException;21 boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;22 boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;23 24 Class<?> getType(String name) throws NoSuchBeanDefinitionException;25 String[] getAliases(String name);26}在BeanFactory里只对IoC容器的基本行为做了定义,根本不关心你的Bean是如何定义及怎样加载的。正如我们只关心能从工厂里得到什么产品,不关心工厂是怎么生产这些产品的。
BeanFactory有一个很重要的子接口,就是ApplicationContext接口,该接口主要来规范容器中的bean对象是非延时加载,即在创建容器对象的时候就对象bean进行初始化,并存储到一个容器中。

要知道工厂是如何产生对象的,我们需要看具体的IoC容器实现,Spring提供了许多IoC容器实现,比如:
Spring IoC容器管理我们定义的各种Bean对象及其相互关系,而Bean对象在Spring实现中是以BeanDefinition来描述的,如下面配置文件
xxxxxxxxxx41<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"></bean>23bean标签还有很多属性:4 scope、init-method、destory-method等。其继承体系如下图所示。

Bean的解析过程非常复杂,功能被分得很细,因为这里需要被扩展的地方很多,必须保证足够的灵活性,以应对可能的变化。Bean的解析主要就是对Spring配置文件的解析。这个解析过程主要通过BeanDefinitionReader来完成,看看Spring中BeanDefinitionReader的类结构图,如下图所示。

看看BeanDefinitionReader接口定义的功能来理解它具体的作用:
xxxxxxxxxx211public interface BeanDefinitionReader {23 //获取BeanDefinitionRegistry注册器对象4 BeanDefinitionRegistry getRegistry();56 7 ResourceLoader getResourceLoader();89 10 ClassLoader getBeanClassLoader();1112 BeanNameGenerator getBeanNameGenerator();1314 /*15 下面的loadBeanDefinitions都是加载bean定义,从指定的资源中16 */17 int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException;18 int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException;19 int loadBeanDefinitions(String location) throws BeanDefinitionStoreException;20 int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException;21}
BeanDefinitionReader用来解析bean定义,并封装BeanDefinition对象,而我们定义的配置文件中定义了很多bean标签,所以就有一个问题,解析的BeanDefinition对象存储到哪儿?答案就是BeanDefinition的注册中心,而该注册中心顶层接口就是BeanDefinitionRegistry。
xxxxxxxxxx211public interface BeanDefinitionRegistry extends AliasRegistry {23 //往注册表中注册bean4 void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)5 throws BeanDefinitionStoreException;67 //从注册表中删除指定名称的bean8 void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;910 //获取注册表中指定名称的bean11 BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;12 13 //判断注册表中是否已经注册了指定名称的bean14 boolean containsBeanDefinition(String beanName);15 16 //获取注册表中所有的bean的名称17 String[] getBeanDefinitionNames();18 19 int getBeanDefinitionCount();20 boolean isBeanNameInUse(String beanName);21}继承结构图如下:

从上面类图可以看到BeanDefinitionRegistry接口的子实现类主要有以下几个:
DefaultListableBeanFactory
在该类中定义了如下代码,就是用来注册bean
xxxxxxxxxx11private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);SimpleBeanDefinitionRegistry
在该类中定义了如下代码,就是用来注册bean
xxxxxxxxxx11private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(64);
ClassPathXmlApplicationContext对Bean配置资源的载入是从refresh()方法开始的。refresh()方法是一个模板方法,规定了 IoC 容器的启动流程,有些逻辑要交给其子类实现。它对 Bean 配置资源进行载入,ClassPathXmlApplicationContext通过调用其父类AbstractApplicationContext的refresh()方法启动整个IoC容器对Bean定义的载入过程。
现要对下面的配置文件进行解析,并自定义Spring框架的IOC对涉及到的对象进行管理。
xxxxxxxxxx71 2<beans>3 <bean id="userService" class="com.itheima.service.impl.UserServiceImpl">4 <property name="userDao" ref="userDao"></property>5 </bean>6 <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"></bean>7</beans>用于封装bean的属性,体现到上面的配置文件就是封装bean标签的子标签property标签数据。
xxxxxxxxxx391public class PropertyValue {23 private String name;4 private String ref;5 private String value;67 public PropertyValue() {8 }910 public PropertyValue(String name, String ref,String value) {11 this.name = name;12 this.ref = ref;13 this.value = value;14 }1516 public String getName() {17 return name;18 }1920 public void setName(String name) {21 this.name = name;22 }2324 public String getRef() {25 return ref;26 }2728 public void setRef(String ref) {29 this.ref = ref;30 }3132 public String getValue() {33 return value;34 }3536 public void setValue(String value) {37 this.value = value;38 }39}
一个bean标签可以有多个property子标签,所以再定义一个MutablePropertyValues类,用来存储并管理多个PropertyValue对象。
xxxxxxxxxx501public class MutablePropertyValues implements Iterable<PropertyValue> {23 private final List<PropertyValue> propertyValueList;45 public MutablePropertyValues() {6 this.propertyValueList = new ArrayList<PropertyValue>();7 }89 public MutablePropertyValues(List<PropertyValue> propertyValueList) {10 this.propertyValueList = (propertyValueList != null ? propertyValueList : new ArrayList<PropertyValue>());11 }1213 public PropertyValue[] getPropertyValues() {14 return this.propertyValueList.toArray(new PropertyValue[0]);15 }1617 public PropertyValue getPropertyValue(String propertyName) {18 for (PropertyValue pv : this.propertyValueList) {19 if (pv.getName().equals(propertyName)) {20 return pv;21 }22 }23 return null;24 }2526 27 public Iterator<PropertyValue> iterator() {28 return propertyValueList.iterator();29 }3031 public boolean isEmpty() {32 return this.propertyValueList.isEmpty();33 }3435 public MutablePropertyValues addPropertyValue(PropertyValue pv) {36 for (int i = 0; i < this.propertyValueList.size(); i++) {37 PropertyValue currentPv = this.propertyValueList.get(i);38 if (currentPv.getName().equals(pv.getName())) {39 this.propertyValueList.set(i, new PropertyValue(pv.getName(),pv.getRef(), pv.getValue()));40 return this;41 }42 }43 this.propertyValueList.add(pv);44 return this;45 }4647 public boolean contains(String propertyName) {48 return getPropertyValue(propertyName) != null;49 }50}
BeanDefinition类用来封装bean信息的,主要包含id(即bean对象的名称)、class(需要交由spring管理的类的全类名)及子标签property数据。
xxxxxxxxxx341public class BeanDefinition {2 private String id;3 private String className;45 private MutablePropertyValues propertyValues;67 public BeanDefinition() {8 propertyValues = new MutablePropertyValues();9 }1011 public String getId() {12 return id;13 }1415 public void setId(String id) {16 this.id = id;17 }1819 public String getClassName() {20 return className;21 }2223 public void setClassName(String className) {24 this.className = className;25 }2627 public void setPropertyValues(MutablePropertyValues propertyValues) {28 this.propertyValues = propertyValues;29 }3031 public MutablePropertyValues getPropertyValues() {32 return propertyValues;33 }34}
BeanDefinitionRegistry接口定义了注册表的相关操作,定义如下功能:
xxxxxxxxxx171public interface BeanDefinitionRegistry {23 //注册BeanDefinition对象到注册表中4 void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);56 //从注册表中删除指定名称的BeanDefinition对象7 void removeBeanDefinition(String beanName) throws Exception;89 //根据名称从注册表中获取BeanDefinition对象10 BeanDefinition getBeanDefinition(String beanName) throws Exception;1112 boolean containsBeanDefinition(String beanName);1314 int getBeanDefinitionCount();1516 String[] getBeanDefinitionNames();17}
该类实现了BeanDefinitionRegistry接口,定义了Map集合作为注册表容器。
xxxxxxxxxx341public class SimpleBeanDefinitionRegistry implements BeanDefinitionRegistry {23 private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<String, BeanDefinition>();45 6 public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {7 beanDefinitionMap.put(beanName,beanDefinition);8 }910 11 public void removeBeanDefinition(String beanName) throws Exception {12 beanDefinitionMap.remove(beanName);13 }1415 16 public BeanDefinition getBeanDefinition(String beanName) throws Exception {17 return beanDefinitionMap.get(beanName);18 }1920 21 public boolean containsBeanDefinition(String beanName) {22 return beanDefinitionMap.containsKey(beanName);23 }2425 26 public int getBeanDefinitionCount() {27 return beanDefinitionMap.size();28 }2930 31 public String[] getBeanDefinitionNames() {32 return beanDefinitionMap.keySet().toArray(new String[1]);33 }34}
BeanDefinitionReader是用来解析配置文件并在注册表中注册bean的信息。定义了两个规范:
xxxxxxxxxx71public interface BeanDefinitionReader {23 //获取注册表对象4 BeanDefinitionRegistry getRegistry();5 //加载配置文件并在注册表中进行注册6 void loadBeanDefinitions(String configLocation) throws Exception;7}
XmlBeanDefinitionReader类是专门用来解析xml配置文件的。该类实现BeanDefinitionReader接口并实现接口中的两个功能。
xxxxxxxxxx481public class XmlBeanDefinitionReader implements BeanDefinitionReader {23 private BeanDefinitionRegistry registry;45 public XmlBeanDefinitionReader() {6 this.registry = new SimpleBeanDefinitionRegistry();7 }89 10 public BeanDefinitionRegistry getRegistry() {11 return registry;12 }1314 15 public void loadBeanDefinitions(String configLocation) throws Exception {1617 InputStream is = this.getClass().getClassLoader().getResourceAsStream(configLocation);18 SAXReader reader = new SAXReader();19 Document document = reader.read(is);20 Element rootElement = document.getRootElement();21 //解析bean标签22 parseBean(rootElement);23 }2425 private void parseBean(Element rootElement) {2627 List<Element> elements = rootElement.elements();28 for (Element element : elements) {29 String id = element.attributeValue("id");30 String className = element.attributeValue("class");31 BeanDefinition beanDefinition = new BeanDefinition();32 beanDefinition.setId(id);33 beanDefinition.setClassName(className);34 List<Element> list = element.elements("property");35 MutablePropertyValues mutablePropertyValues = new MutablePropertyValues();36 for (Element element1 : list) {37 String name = element1.attributeValue("name");38 String ref = element1.attributeValue("ref");39 String value = element1.attributeValue("value");40 PropertyValue propertyValue = new PropertyValue(name,ref,value);41 mutablePropertyValues.addPropertyValue(propertyValue);42 }43 beanDefinition.setPropertyValues(mutablePropertyValues);4445 registry.registerBeanDefinition(id,beanDefinition);46 }47 }48}
在该接口中定义IOC容器的统一规范即获取bean对象。
xxxxxxxxxx61public interface BeanFactory {2 //根据bean对象的名称获取bean对象3 Object getBean(String name) throws Exception;4 //根据bean对象的名称获取bean对象,并进行类型转换5 <T> T getBean(String name, Class<? extends T> clazz) throws Exception;6}
该接口的所以的子实现类对bean对象的创建都是非延时的,所以在该接口中定义 refresh() 方法,该方法主要完成以下两个功能:
xxxxxxxxxx41public interface ApplicationContext extends BeanFactory {2 //进行配置文件加载并进行对象创建3 void refresh() throws IllegalStateException, Exception;4}
作为ApplicationContext接口的子类,所以该类也是非延时加载,所以需要在该类中定义一个Map集合,作为bean对象存储的容器。
声明BeanDefinitionReader类型的变量,用来进行xml配置文件的解析,符合单一职责原则。
BeanDefinitionReader类型的对象创建交由子类实现,因为只有子类明确到底创建BeanDefinitionReader哪儿个子实现类对象。
xxxxxxxxxx291public abstract class AbstractApplicationContext implements ApplicationContext {23 protected BeanDefinitionReader beanDefinitionReader;4 //用来存储bean对象的容器 key存储的是bean的id值,value存储的是bean对象5 protected Map<String, Object> singletonObjects = new HashMap<String, Object>();67 //存储配置文件的路径8 protected String configLocation;910 public void refresh() throws IllegalStateException, Exception {1112 //加载BeanDefinition13 beanDefinitionReader.loadBeanDefinitions(configLocation);1415 //初始化bean16 finishBeanInitialization();17 }1819 //bean的初始化20 private void finishBeanInitialization() throws Exception {21 BeanDefinitionRegistry registry = beanDefinitionReader.getRegistry();22 String[] beanNames = registry.getBeanDefinitionNames();2324 for (String beanName : beanNames) {25 BeanDefinition beanDefinition = registry.getBeanDefinition(beanName);26 getBean(beanName);27 }28 }29}注意:该类finishBeanInitialization()方法中调用getBean()方法使用到了模板方法模式。
该类主要是加载类路径下的配置文件,并进行bean对象的创建,主要完成以下功能:
xxxxxxxxxx671public class ClassPathXmlApplicationContext extends AbstractApplicationContext{23 public ClassPathXmlApplicationContext(String configLocation) {4 this.configLocation = configLocation;5 //构建XmlBeanDefinitionReader对象6 beanDefinitionReader = new XmlBeanDefinitionReader();7 try {8 this.refresh();9 } catch (Exception e) {10 }11 }1213 //根据bean的id属性值获取bean对象14 15 public Object getBean(String name) throws Exception {1617 //return singletonObjects.get(name);18 Object obj = singletonObjects.get(name);19 if(obj != null) {20 return obj;21 }2223 BeanDefinitionRegistry registry = beanDefinitionReader.getRegistry();24 BeanDefinition beanDefinition = registry.getBeanDefinition(name);25 if(beanDefinition == null) {26 return null;27 }28 String className = beanDefinition.getClassName();29 Class<?> clazz = Class.forName(className);30 Object beanObj = clazz.newInstance();31 MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();32 for (PropertyValue propertyValue : propertyValues) {33 String propertyName = propertyValue.getName();34 String value = propertyValue.getValue();35 String ref = propertyValue.getRef();36 if(ref != null && !"".equals(ref)) {3738 Object bean = getBean(ref);39 String methodName = StringUtils.getSetterMethodNameByFieldName(propertyName);40 Method[] methods = clazz.getMethods();41 for (Method method : methods) {42 if(method.getName().equals(methodName)) {43 method.invoke(beanObj,bean);44 }45 }46 }4748 if(value != null && !"".equals(value)) {49 String methodName = StringUtils.getSetterMethodNameByFieldName(propertyName);50 Method method = clazz.getMethod(methodName, String.class);51 method.invoke(beanObj,value);52 }53 }54 singletonObjects.put(name,beanObj);55 return beanObj;56 }5758 59 public <T> T getBean(String name, Class<? extends T> clazz) throws Exception {6061 Object bean = getBean(name);62 if(bean != null) {63 return clazz.cast(bean);64 }65 return null;66 }67}
spring框架其实使用到了很多设计模式,如AOP使用到了代理模式,选择JDK代理或者CGLIB代理使用到了策略模式,还有适配器模式,装饰者模式,观察者模式等。
spring框架底层是很复杂的,进行了很深入的封装,并对外提供了很好的扩展性。而我们自定义SpringIOC有以下几个目的: