目录
BeanFactory和ApplicationContext的区别
Spring设计模式内容,读者如果阅读过 自己实现Spring简易版解析 或许有不一样的感受哦

Spring中工厂模式的应用
Spring设计理念
-
Spring是面向Bean的编程(BOP:Bean Oriented Programming),Bean在Spring中才是真正的主角。Bean在Spring中作用就像Object对OOP的意义一样,没有对象的概念就像没有面向对象编程,Spring中没有Bean也就没有Spring存在的意义。Spring提供了IoC 容器通过配置文件或者注解的方式来管理对象之间的依赖关系。
-
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫"依赖查找"(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。
Spring中Bean组件定义相关

-
Bean的定义 解析Bean的配置信息,封装到BeanDefinition中
-
Bean的创建 使用反射创建bean对象 id
-
Bean的解析 赋值、初始化等操作。
Spring Bean的创建是典型的工厂模式,它的顶级接口是BeanFactory。
职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。
BeanFactory有三个子类:ListableBeanFactory、HierarchicalBeanFactory和AutowireCapableBeanFactory。目的是为了区分Spring内部对象处理和转化的数据限制。
但从图中可以发现最终的默认实现类是DefaultListableBeanFactory,它实现了所有的接口。
Spring中的BeanFactory就是简单工厂模式的体现,根据传入一个唯一的标识来获得Bean对象
BeanFactory,以Factory结尾,表示它是一个工厂(接口), 它负责生产和管理bean的一个工厂。在Spring中,BeanFactory是工厂的顶层接口,也是IOC容器的核心接口,因此BeanFactory中定义了管理Bean的通用方法 ,如 getBean 和 containsBean 等.
BeanFactory只是个接口,并不是IOC容器的具体实现,所以Spring容器给出了很多种实现,如 DefaultListableBeanFactory 、XmlBeanFactory 、ApplicationContext等,其中XmlBeanFactory就是常用的一个,该实现将以XML方式描述组成应用的对象及对象间的依赖关系。
BeanFactory源码&使用情景
-
从IOC容器中获取Bean(Name or Type)
-
检索IOC容器中是否包含了指定的对象
-
判断Bean是否为单例
java
public interface BeanFactory {
/**
对FactoryBean的转移定义,因为如果使用bean的名字来检索FactoryBean得到的是对象是工厂生成的对象,
如果想得到工厂本身就需要转移
*/
String FACTORY_BEAN_PREFIX = "&";
//根据Bean的名字 获取IOC容器中对应的实例
Object getBean(String var1) throws BeansException;
//根据Bean的名字和class类型得到bean实例,增加了类型安全验证机制
<T> T getBean(String var1, Class<T> var2) throws BeansException;
Object getBean(String var1, Object... var2) throws BeansException;
<T> T getBean(Class<T> var1) throws BeansException;
<T> T getBean(Class<T> var1, Object... var2) throws BeansException;
<T> ObjectProvider<T> getBeanProvider(Class<T> var1);
<T> ObjectProvider<T> getBeanProvider(ResolvableType var1);
//查看Bean容器中是否存在对应的实例,存在返回true 否则返回false
boolean containsBean(String var1);
//根据Bean的名字 判断这个bean是不是单例
boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;
//得到bean实例的class类型
@Nullable
Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
@Nullable
Class<?> getType(String var1, boolean var2) throws NoSuchBeanDefinitionException;
//得到bean的别名
String[] getAliases(String var1);
}
Spring中的FactoryBean
FactoryBean是一个Bean,但又不仅仅是一个Bean,这样听起来矛盾,但为啥又这样说呢?其实在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的。但对FactoryBean而言,这个FactoryBean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂方法模式和装饰器模式类似
java
public interface FactoryBean<T> {
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
/**
getObject()方法: 会返回该FactoryBean生产的对象实例,我们需要实现该方法,以给出自己的对象实例化逻辑
这个方法也是FactoryBean的核心.
*/
@Nullable
T getObject() throws Exception;
/**
getObjectType()方法: 仅返回getObject() 方法所返回的对象类型,如果预先无法确定,返回NULL,
这个方法返回类型是在IOC容器中getBean所匹配的类型
*/
@Nullable
Class<?> getObjectType();
//该方法的结果用于表明 工厂方法getObject() 所生产的 对象是否要以单例形式存储在容器中如果以单例存在就返回true,否则返回false
default boolean isSingleton() {
return true;
}
}
为什么需要FactoryBean?
-
在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,则需要在中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。Spring为此提供了一个
org.springframework.bean.factory.FactoryBean
的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。FactoryBean接口对于Spring框架来说占用重要的地位,Spring自身就提供了70多个FactoryBean的实现。它们隐藏了实例化一些复杂Bean的细节,给上层应用带来了便利。 -
由于第三方库不能直接注册到spring容器,于是可以实现
org.springframework.bean.factory.FactoryBean
接口,然后给出自己对象的实例化代码即可。
FactoryBean的使用特点?
- 当用户使用容器本身时,可以使用转义字符"&"来得到FactoryBean本身,以区别通过FactoryBean产生的实例对象和FactoryBean对象本身。
FactoryBean表现的是一个工厂的职责,如果一个BeanA 是实现FactoryBean接口,那么A就是变成了一个工厂,根据A的名称获取到的实际上是工厂调用getObject()方法返回的对象,而不是对象本身,如果想获取工厂对象本身,需要在名称前面加上 '&'符号
-
getObject('name') 返回的是工厂中工厂方法生产的实例
-
getObject('&name') 返回的是工厂本身实例
使用场景
- FactoryBean的最为经典的使用场景,就是用来创建AOP代理对象,这个对象在Spring中就是 ProxyFactoryBean
BeanFactory与FactoryBean区别
-
他们两个都是工厂,但是FactoryBean本质还是一个Bean,也归BeanFactory管理
-
BeanFactory是Spring容器的顶层接口,FactoryBean更类似于用户自定义的工厂接口
BeanFactory和ApplicationContext的区别
-
BeanFactory是Spring容器的顶层接口,而ApplicationContext应用上下文类 他是BeanFactory的子类,他是Spring中更高级的容器,提供了更多的功能
-
国际化
-
访问资源
-
载入多个上下文
-
消息发送 响应机制
-
-
两者的装载bean的时机不同
-
BeanFactory: 在系统启动的时候不会去实例化bean,只有从容器中拿bean的时候才会去实例化(懒加载)
- 优点: 应用启动的时候占用的资源比较少,对资源的使用要求比较高的应用 ,比较有优势
-
ApplicationContext:在启动的时候就把所有的Bean全部实例化。
-
lazy-init= true 可以使bean延时实例化
-
优点: 所有的Bean在启动的时候就加载,系统运行的速度快,还可以及时的发现系统中配置的问题。
-
-
Spring中观察者模式应用
观察者模式(发布-订阅(Publish/Subscribe)模式)它是用于建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应的作出反应。
在观察者模式中发生改变的对象称为观察目标 ,而被通知的对象称为观察者,一个观察目标可以应对多个观察者,而且这些观察者之间可以没有任何相互联系,可以根据需要增加和删除观察者,使得系统更易于扩展。
观察者和被观察者,是松耦合的关系;发布者和订阅者,则完全不存在耦合。
-
在设计模式结构上,发布订阅模式继承自观察者模式,是观察者模式的一种实现的变体。
-
在设计模式意图上,两者关注点不同,一个关心数据源,一个关心的是事件消息。
-
观察者模式:数据源直接通知订阅者发生改变。
-
发布订阅模式:数据源告诉第三方(事件通道)发生了改变,第三方再通知订阅者发生了改变。
-

Spring中观察者模式
Spring 基于观察者模式,实现了自身的事件机制也就是事件驱动模型,事件驱动模型通常也被理解成观察者或者发布/订阅模型。
Spring事件模型提供如下几个角色
-
【事件】ApplicationEvent:是所有事件对象的父类。ApplicationEvent 继承自 jdk 的 EventObject, 所有的事件都需要继承 ApplicationEvent, 并且通过 source 得到事件源。
-
ContextRefreshEvent,当ApplicationContext容器初始化完成或者被刷新的时候,就会发布该事件。
-
ContextStartedEvent,当ApplicationContext启动的时候发布事件.
-
ContextStoppedEvent,当ApplicationContext容器停止的时候发布事件.
-
RequestHandledEvent,只能用于DispatcherServlet的web应用,Spring处理用户请求结束后,系统会触发该事件。
-
-
【事件监听】ApplicationListener:
-
ApplicationListener(应用程序事件监听器) 继承自jdk的EventListener,所有的监听器都要实现这个接口,这个接口只有一个onApplicationEvent()方法,该方法接受一个ApplicationEvent或其子类对象作为参数
-
在方法体中,可以通过不同对Event类的判断来进行相应的处理.当事件触发时所有的监听器都会收到消息,如果你需要对监听器的接收顺序有要求,可是实现该接口的一个实现SmartApplicationListener,通过这个接口可以指定监听器接收事件的顺序。
-
实现了ApplicationListener接口之后,需要实现方法onApplicationEvent(),在容器将所有的Bean都初始化完成之后,就会执行该方法。
-
-
【事件源】ApplicationEventPublisher:事件的发布者,封装了事件发布功能方法接口,是Applicationcontext接口的超类
-
事件机制的实现需要三个部分,事件源,事件,事件监听器,ApplicationEvent就相当于事件,ApplicationListener相当于事件监听器,ApplicationEventPublisher相当于时间源。
-
我们常用的ApplicationContext都继承了AbstractApplicationContext,像我们平时常见ClassPathXmlApplicationContext、XmlWebApplicationContex也都是继承了它,AbstractApplicationcontext是ApplicationContext接口的抽象实现类,在该类中实现了publishEvent方法
-
-
【事件管理】ApplicationEventMulticaster:用于事件监听器的注册和事件的广播。监听器的注册就是通过它来实现的,它的作用是把 Applicationcontext 发布的 Event 广播给它的监听器列表。
javapublic interface ApplicationEventMulticaster { //添加事件监听器 void addApplicationListener(ApplicationListener<?> var1); //添加事件监听器,使用容器中的bean void addApplicationListenerBean(String var1); //移除事件监听器 void removeApplicationListener(ApplicationListener<?> var1); void removeApplicationListenerBean(String var1); //移除所有 void removeAllListeners(); //发布事件 void multicastEvent(ApplicationEvent var1); void multicastEvent(ApplicationEvent var1, @Nullable ResolvableType var2); } // 在AbstractApplicationcontext中有一个applicationEventMulticaster // 的成员变量, // 提供了监听器Listener的注册方法 public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext, DisposableBean { private ApplicationEventMulticaster applicationEventMulticaster; protected void registerListeners() { // Register statically specified listeners first. for (ApplicationListener<?> listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let post-processors apply to them! String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false); for (String lisName : listenerBeanNames) { getApplicationEventMulticaster().addApplicationListenerBean(lisName); } } }
事件机制工作流程

监听器什么时候注册到IOC容器
注册的开始逻辑是在AbstractApplicationContext类的refresh方法,该方法包含了整个IOC容器初始化所有方法。其中有一个registerListeners()方法就是注册系统监听者(Spring自带的)和自定义监听器的。
java
public void refresh() throws BeansException, IllegalStateException {
// BeanFactory准备工作完成后进行的后置处理工作
this.postProcessBeanFactory(beanFactory);
// 执行BeanFactoryPostProcessor的方法;
this.invokeBeanFactoryPostProcessors(beanFactory);
// 注册BeanPostProcessor(Bean的后置处理器),在创建bean的前后等执行
this.registerBeanPostProcessors(beanFactory);
// 初始化MessageSource组件(做国际化功能;消息绑定,消息解析);
this.initMessageSource();
// 初始化事件派发器
this.initApplicationEventMulticaster();
// 子类重写这个方法,在容器刷新的时候可以自定义逻辑;如创建Tomcat,Jetty等WEB服务器
this.onRefresh();
// 注册应用的监听器。就是注册实现了ApplicationListener接口的监听器bean,这些监听器是注册到ApplicationEventMulticaster中的
this.registerListeners();
// 初始化所有剩下的非懒加载的单例bean
this.finishBeanFactoryInitialization(beanFactory);
// 完成context的刷新
this.finishRefresh();
}
看registerListeners的关键方法体,其中的两个方法addApplicationListener和addApplicationListenerBean
,从方法可以看出是添加监听者。
java
protected void registerListeners() {
Iterator var1 = this.getApplicationListeners().iterator();
while(var1.hasNext()) {
ApplicationListener<?> listener = (ApplicationListener)var1.next();
this.getApplicationEventMulticaster().addApplicationListener(listener);
}
String[] listenerBeanNames = this.getBeanNamesForType(ApplicationListener.class, true, false);
String[] var7 = listenerBeanNames;
int var3 = listenerBeanNames.length;
for(int var4 = 0; var4 < var3; ++var4) {
String listenerBeanName = var7[var4];
this.getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
}
该接口主要两个职责,维护ApplicationListener相关类和发布事件。实现在默认实现类AbstractApplicationEventMulticaster,最后将Listener放到了内部类ListenerRetriever两个set集合中
java
private class ListenerRetriever {
public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet();
public final Set<String> applicationListenerBeans = new LinkedHashSet();
}
ListenerRetriever被称为监听器注册表。
Spring如何发布的事件并通知监听者
这个注意的有两个方法
publishEvent方法
AbstractApplicationContext
实现了ApplicationEventPublisher
接口的publishEvent
方法
java
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
Object applicationEvent;
//尝试转换为ApplicationEvent或者PayloadApplicationEvent,如果是PayloadApplicationEvent则获取eventType
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent)event;
} else {
applicationEvent = new PayloadApplicationEvent(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent)applicationEvent).getResolvableType();
}
}
if (this.earlyApplicationEvents != null) {
//判断earlyApplicationEvents是否为空(也就是早期事件还没有被发布-说明广播器还没有实例化好),如果不为空则将当前事件放入集合
this.earlyApplicationEvents.add(applicationEvent);
} else {
//否则获取ApplicationEventMulticaster调用其multicastEvent将事件广播出去。本文这里获取到的广播器实例是SimpleApplicationEventMulticaster。
this.getApplicationEventMulticaster().multicastEvent((ApplicationEvent)applicationEvent, eventType);
}
//将事件交给父类处理
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext)this.parent).publishEvent(event, eventType);
} else {
this.parent.publishEvent(event);
}
}
}
multicastEvent方法 继续进入到multicastEvent方法
,该方法有两种方式调用invokeListener,通过线程池和直接调用,进一步说就是通过异步和同步两种方式调用.
java
public void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType) {
//解析事件类型
ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
//获取执行器
Executor executor = this.getTaskExecutor();
// 获取合适的ApplicationListener,循环调用监听器的onApplicationEvent方法
Iterator var5 = this.getApplicationListeners(event, type).iterator();
while(var5.hasNext()) {
ApplicationListener<?> listener = (ApplicationListener)var5.next();
if (executor != null) {
//如果executor不为null,则交给executor去调用监听器
executor.execute(() -> {
this.invokeListener(listener, event);
});
} else {
//否则,使用当前主线程直接调用监听器;
this.invokeListener(listener, event);
}
}
}
invokeListener方法
java
// 该方法增加了错误处理逻辑,然后调用doInvokeListener
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = this.getErrorHandler();
if (errorHandler != null) {
try {
this.doInvokeListener(listener, event);
} catch (Throwable var5) {
errorHandler.handleError(var5);
}
} else {
this.doInvokeListener(listener, event);
}
}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
//直接调用了listener接口的onApplicationEvent方法
listener.onApplicationEvent(event);
}