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);
目前先写到这么多,后续有新的想法继续增添内容。
