Spring IoC即通过Spring IoC容器来负责容器的生命周期管理及容器对象之间的依赖关系。
初始如下常见代码示例中【小明想吃牛肉】:
public class Beef{
...
}
public class XiaoMing{
private Beef beef;
public XiaoMing(){
beef = new Beef();
}
public void eat(){
....;
}}
这里通过 new Beef() 生成一个新的对象进行 XiaoMing 的 Beef 属性的赋值,但是如果小明明后天想吃鱼肉、鸡肉 等情况下,我们不得不去手动修改 new 的部分,而且需要程序员自己去维护这个对象之间的依赖关系。
IoC的概念出现
IoC一般的解释为控制反转,那么什么是控制反转?
原来由程序员控制的对象依赖关系扔给 Spring IoC 容器去进行处理。
以下的内容不包括配置 xml 文件来描述 各个 Bean 之间的关系。
由此引出了DI 依赖注入的概念
这里先抛开 IoC的明细内容。
通过以上代码,我们是通过在构造器中手动new 一个对象注入,这里的入口控制是在 内部的 new 对象构造中,如果需要改变我们不得不改变代码,那么如何进行依赖注入的控制 使得代码的使用更加灵活,引入依赖注入的三种方式。
- 构造器注入:这里虽然也是构造器注入,但是我们将代码入口的可控制性提升到参数入口层面,可以想象下,原来我们是通过在XiaoMing的构造器内部 new 新的对象,现在我们只需要在 XiaoMing 的调用处进行控制,控制的入口暴露的更加上层了。不会关心内部的具体实现。同时我们只要将 具体类 Beef 抽象成抽象接口 Meat【在这里举例可能不够丰满】,在runtime 时候会根据具体的实现类进行灵活的调整,这样在鱼、鸡肉等肉食情况下我们都能满足。
public interface Meat{}
public class XiaoMing{
private Meat meat;
public XiaoMing(Meat meat){
this.meat = meat;
}
...}
- setter 注入:其实本质上和上一条没多大区别,只是具体实现的差异罢了。当然这里的控制更加灵活,在小明想好想吃啥的时候再进行控制吃啥,避免了在构造小明对象的时候就已经决定了吃啥。
pubclic interface Meat{}
public class XiaoMing{
private Meat meat;
public XiaoMing(){}
public void setMeat(Meat meat){
this.meat = meat;
}
}
- interface 接口注入:使用的不多,主要解释为被依赖的对象实现了其他不必要的接口,带有侵入性。
IoC 和 DI 的区别:个人理解 IoC 其实是一种理论思想而 DI 则更偏向于 具体实现
IoC 容器种类
在Spring 中我们的 Bean 全权托付给 IoC 容器管理,常见的 IoC 容器一般分为 BeanFactory、ApplicationContext 两种。
BeanFactory
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String var1) throws BeansException;
<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);
boolean containsBean(String var1);
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;
@Nullable
Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
String[] getAliases(String var1);
}
可以发现BeanFactory实际上就是一个Interface接口,提供了基本能力行为约束。
ApplicationContext
通过源码发现我们会发现实际上ApplicationContext 实际上是扩展了BeanFactory接口,进行了功能增强。
- BeanFactory
- ApplicationEventPublisher:用于封装事件接口功能,向事件监听器发送消息
- ResourceLoader:Spring 顶层 资源加载器,用于加载资源
- MessageSource:解析Message策略接口,比如支持国际化等
- EnvironmentCable:用于获取Env的接口。
通过继承关系举例,WebServerApplicationContext是 ApplicationContext 的直接子接口,ConfigurableWebServerApplicationContext是 ConfigableApplicationContext和WebServerApplicationContext的共同子类。
//用于获取Web相关的上下文。
public interface WebServerApplicationContext extends ApplicationContext {
WebServer getWebServer();
String getServerNamespace();
}
//包括了对于生命周期及资源释放关闭的功能。
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
String CONFIG_LOCATION_DELIMITERS = ",; \t\n";
String CONVERSION_SERVICE_BEAN_NAME = "conversionService";
String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";
String ENVIRONMENT_BEAN_NAME = "environment";
String SYSTEM_PROPERTIES_BEAN_NAME = "systemProperties";
String SYSTEM_ENVIRONMENT_BEAN_NAME = "systemEnvironment";
void setId(String var1);
void setParent(@Nullable ApplicationContext var1);
void setEnvironment(ConfigurableEnvironment var1);
ConfigurableEnvironment getEnvironment();
void addBeanFactoryPostProcessor(BeanFactoryPostProcessor var1);
void addApplicationListener(ApplicationListener<?> var1);
void addProtocolResolver(ProtocolResolver var1);
void refresh() throws BeansException, IllegalStateException;
void registerShutdownHook();
void close();
boolean isActive();
ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
}
相比较而言 BeanFactory 为低级容器工厂,而ApplicationContext为高级容器工厂,里面增强了新的功能。
常见的BeanFactory 为XmlBeanFactory,不过现已被建议废弃。
/** @deprecated */
@Deprecated
public class XmlBeanFactory extends DefaultListableBeanFactory {
private final XmlBeanDefinitionReader reader;
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, (BeanFactory)null);
}
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader = new XmlBeanDefinitionReader(this);
this.reader.loadBeanDefinitions(resource);
}
}
在此包下面我们会看到常见的扩展于ApplicationContext的常见容器工厂,比较常见的为
- ClassPathXmlApplicationContext
- FileSystemXmlApplicationContext
- XmlWebApplicationContext
举例ClassPathXmlApplicationContext
简单示例:
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
StudentService studentService = (StudentService)ac.getBean("studentService");
关键性的顶层接口有:
- BeanFactory: Spring 容器管理
- ResourcePatterReslover: 资源加载
- MessageSource:message国际化
- Closeable:资源释放关闭
- LifeCycle:生命周期管理
- InitializingBean:自定义初始化
- BeanNameAware:设置 beanName 的 Aware 接口
- ApplicationEventPublisher:事件发布
关键接口详解分析
ApplicationEventPublisher
既然到了事件与监听过程,那么就不得不讲到设计模式中的观察者模式
观察者模式
实际上观察者模式可以抽象为4个部分:
- Subject : 用于抽象 事件动作,同时存放对事件通知者的一些 常规操作,如 add、remove 操作,一般来说事件通知者通过列表来存放,然后抽象需要通知的事件操作。
- Observer:抽象事件通知者
- ConcreteSubject:实现类
- ConcreteObject:实现类
对应的 UML 类图关系如下:
简单的示例代码如下:
public abstract Subject{
protected List<Observer> list = new ArrayList<>();
public void add(Observer o){
list.add(o);
}
public void remove(Observer o){
list.remove(o);
}
public abstract notifyObserver(){}
}
public interface Observer{
void notifyObserver();
}
public class ConcreteSubject extends Subject{
@Override
public void notifyObserver(String msg){
for(Observer item;list){
item.notifyObserver(msg);
}
}
}
public class ConcreteObserver extends Observer{
public void notifyObserver(String msg){
....;
}
}
JDK 中对事件监听机制的支持
深究源码我们发现关键类
public class EventObject implements java.io.Serializable {
private static final long serialVersionUID = 5516075349620653480L;
/**
* The object on which the Event initially occurred.
*/
protected transient Object source;
/**
* Constructs a prototypical Event.
*
* @param source The object on which the Event initially occurred.
* @exception IllegalArgumentException if source is null.
*/
public EventObject(Object source) {
if (source == null)
throw new IllegalArgumentException("null source");
this.source = source;
}
/**
* The object on which the Event initially occurred.
*
* @return The object on which the Event initially occurred.
*/
public Object getSource() {
return source;
}
/**
* Returns a String representation of this EventObject.
*
* @return A a String representation of this EventObject.
*/
public String toString() {
return getClass().getName() + "[source=" + source + "]";
}
}
/**
* A tagging interface that all event listener interfaces must extend.
* @since JDK1.1
*/
public interface EventListener {
}
在此基础上 需要我们根据实际的场景来扩展或者实现以上关键类,综上所述,另外需要自定义的就是时间发布器。
Spring 容器对事件监听的支持
Spring 中对应的如下:
public abstract class ApplicationEvent extends EventObject {
private static final long serialVersionUID = 7099057708183571937L;
private final long timestamp = System.currentTimeMillis();
public ApplicationEvent(Object source) {
super(source);
}
public final long getTimestamp() {
return this.timestamp;
}
}
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E var1);
}
事件发布器为 ApplicationEventPublisher:
@FunctionalInterface
public interface ApplicationEventPublisher {
default void publishEvent(ApplicationEvent event) {
this.publishEvent((Object)event);
}
void publishEvent(Object var1);
}
通过关系图如下:
通过继承关系继续深究:
深究源码发现:
所以,真正的事件发布器是ApplicationEventMulticaster,这是一个接口,定义了事件发布器需要具备的基本功能:管理事件监听器以及发布事件。其默认实现类是
SimpleApplicationEventMulticaster,该组件会在容器启动时被自动创建,并以单例的形式存在,管理了所有的事件监听器,并提供针对所有容器内事件的发布功能。
简述IoC实现机制
简单的理解就是 工厂模式+反射机制
public interface Fruit{
void eat();
}
public class Apple implements Fruit{
@Override
publict void eat(){
...;
}
}
public class Orange implements Fruit{
@Overrid
public void eat(){
...;
}
}
public class Factory{
public static getInstance(String str){
Fruit f= null;
try{
f = (Fruit)Class.forName(str).newInstance();
}catch (Exception e){
e.printStackTrace();
}
return f;
}
}
BeanFactory 与 FactoryBean 区别
在Spring 中很多博客中我们会看到BeanFactory及FactoryBean的区别分析,在此我也记录下个人理解。
BeanFactory 可以提供对Bean 的实例化与管理,另外Spring 也提供了FactoryBean 让我们来做自定义增强,比如一些逻辑的实现与处理的Bean扩展,通过xml配置实现比较困难。
public interface FactoryBean<T> {
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
在FactoryBean 中应用了工厂模式及装饰器模式。这样可以将复杂的Bean实例化过程封装起来,让使用者无需关系具体的实现过程。
Spring 框架中的事件类型
Spring 提供了5 种标准的事件类型:
上下文更新事件
- ContextRefreshedEvent 事件,该事件会在ApplicationContext被初始化或者更新时发布,也可以在调用ConfigurableApplicationContext 接口中的 #refresh() 方法时被触发。
- 上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext 的 #start() 方法开始/重新开始容器时触发该事件。
- 上下文停止事件(ContextStoppedEvent):当容器调用 ConfigurableApplicationContext 的 #stop() 方法停止容器时触发该事件。
- 上下文关闭事件(ContextClosedEvent):当ApplicationContext 被关闭时触发该事件。容器被关闭时,其管理的所有单例 Bean 都被销毁。
- 请求处理事件(RequestHandledEvent):在 We b应用中,当一个HTTP 请求(request)结束触发该事件。
如何实现自定义的事件:
- 扩展 ApplicationEvent 实现自定义的事件
public class CustomApplicationEvent extends ApplicationEvent{
public CustomApplicationEvent(Object source, final String msg) {
super(source);
}
}
- 创建自定义的监听器
public class CustomApplicationListener implements ApplicationListener<CustomApplicationEvent> {
@Override
public void onApplicationEvent(CustomApplicationEvent applicationEvent) {
....;
}
}
- 通过ApplicationContext 的 publishEvent 进行发布
// 创建 CustomApplicationEvent 事件
CustomApplicationEvent customEvent = new CustomApplicationEvent(applicationContext, "Test message");
// 发布事件
applicationContext.publishEvent(customEvent);
目前先写到这么多,后续有新的想法继续增添内容。