分析Spring中的计划模式(一) | 工厂&观察者
目次
Spring中工厂模式的应用
Spring计划理念
Spring中Bean组件界说相干
BeanFactory源码&使用景象
Spring中的FactoryBean
为什么必要FactoryBean?
FactoryBean的使用特点?
使用场景
BeanFactory与FactoryBean区别
BeanFactory和ApplicationContext的区别
Spring中观察者模式应用
Spring中观察者模式
变乱机制工作流程
监听器什么时间注册到IOC容器
Spring怎样发布的变乱并关照监听者
Spring计划模式内容,读者假如阅读过 本身实现Spring浅易版分析 大概有不一样的感受哦
https://i-blog.csdnimg.cn/direct/d87249e673d94cd5a37a030cdcc3497c.png
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组件界说相干
https://i-blog.csdnimg.cn/direct/8f77ba7e13344705bf5cfee5e172a74e.png
[*] 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是否为单例
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,它的实现与计划模式中的工厂方法模式和装饰器模式类似
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)模式)它是用于创建一种对象与对象之间的依赖关系,一个对象发生改变时将主动关照其他对象,其他对象将相应的作出反应。
在观察者模式中发生改变的对象称为观察目的,而被关照的对象称为观察者,一个观察目的可以应对多个观察者,而且这些观察者之间可以没有任何相互接洽,可以根据必要增长和删除观察者,使得体系更易于扩展。
观察者和被观察者,是松耦合的关系;发布者和订阅者,则完全不存在耦合。
[*] 在计划模式结构上,发布订阅模式继承自观察者模式,是观察者模式的一种实现的变体。
[*] 在计划模式意图上,两者关注点差别,一个关心数据源,一个关心的是变乱消息。
[*] 观察者模式:数据源直接关照订阅者发生改变。
[*] 发布订阅模式:数据源告诉第三方(变乱通道)发生了改变,第三方再关照订阅者发生了改变。
https://i-blog.csdnimg.cn/direct/75a19bf610ec46cf9f87f6d89bbaab33.png
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 广播给它的监听器列表。
public 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);
}
}
}
变乱机制工作流程
https://i-blog.csdnimg.cn/direct/666ff77548d84e7199a273562b79d4da.png
监听器什么时间注册到IOC容器
注册的开始逻辑是在AbstractApplicationContext类的refresh方法,该方法包罗了整个IOC容器初始化全部方法。此中有一个registerListeners()方法就是注册体系监听者(Spring自带的)和自界说监听器的。
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,从方法可以看出是添加监听者。
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;
this.getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
} 该接口重要两个职责,维护ApplicationListener相干类和发布变乱。实如今默认实现类AbstractApplicationEventMulticaster,末了将Listener放到了内部类ListenerRetriever两个set聚集中
private class ListenerRetriever {
public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet();
public final Set<String> applicationListenerBeans = new LinkedHashSet();
} ListenerRetriever被称为监听器注册表。
Spring怎样发布的变乱并关照监听者
这个留意的有两个方法
publishEvent方法
[*] AbstractApplicationContext实现了ApplicationEventPublisher 接口的publishEvent方法
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,通过线程池和直接调用,进一步说就是通过异步和同步两种方式调用.
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方法
// 该方法增加了错误处理逻辑,然后调用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);
}
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]