Spring IoC 学习(3)

简介: 前面因为总结的累了,把IoC的两个步骤,只写了一半,就仅仅把容器启动的方面说了说,对于实例化的阶段,我前面并没有说,在这节中,准备讲一讲,实例化阶段。

前言

前面因为总结的累了,把IoC的两个步骤,只写了一半,就仅仅把容器启动的方面说了说,对于实例化的阶段,我前面并没有说,在这节中,准备讲一讲,实例化阶段。

生命周期

基础生命周期简图

这个部分,其实实例化,一般都是用反射或者cglib,底层封装的也比较深,我随着代码debug的过程中,也没有接触到这个部分。但是在实例化bean的过程中,还是看到了挺多东西。

生命周期的图,基本上有可能是以下这种
image.png | center | 801x332

从图中可以看到,在这个阶段,最重要的不是实例化本身,而是实例化前后会做的一些操作。实例化有些不同的,应该就是在实例化时可能会遇到绑定属性的相关操作,这个时候不是用传统的反射来做,而是用BeanWrapper来包装绑定。有个印象即可。

BeanFactory与ApplicationContext生命周期简图

BeanFactory
image.png | center | 585x501
ApplicationContext
image.png | center | 585x501

以上两图为借用

各种拓展接口

各色的Aware接口

当对象实例化完成并且相关属性以及依赖设置完成之后,Spring容器会检查当前对象实例是否实现了一系列的以Aware命名结尾的接口定义。如果是,则将这些Aware接口定义中规定的依赖注入给当前对象实例。

下面总结一下各种Aware接口以及作用

LoadTimeWeaverAware 加载Spring Bean时织入第三方模块,如AspectJ
BeanClassLoaderAware 加载Spring Bean的类加载器
ResourceLoaderAware 底层访问资源的加载器
BeanFactoryAware 得到BeanFactory引用
ServletConfigAware 得到ServletConfig
ServletContextAware 得到ServletContext
MessageSourceAware 国际化
ApplicationEventPublisherAware 应用事件

BeanPostProcessor

我们看一下这个接口

package org.springframework.beans.factory.config;

import org.springframework.beans.BeansException;

/**
 * 
 */
public interface BeanPostProcessor {

    /**
     *  初始化之前做操作
     */

    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

    /**
     *  初始化之后做操作
     */

    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

BeanPostProcessor的应用场景

① 在注解时使用

在使用Spring构建目的时候,现在应该很多人都习惯于用注解了,因为注解简单。@Component @Controller @Service @Repository @Autowired 等注解来便捷开发,下面来探讨BeanPostProcessor在@Autowired 中的运用。

在使用@Autowired之前需要在容器中配置AutowiredAnnotationBeanPostProcessor。

② 处理Aware接口类

我们可以来看一小段ApplicationContextAwareProcessor的代码

package org.springframework.context.support;

/**
 * 可以看到是实现自BeanPostProcessor的
 */
class ApplicationContextAwareProcessor implements BeanPostProcessor {

    /**
     * 略去部分代码
     */

    /**
     * 在初始化之前做的操作
     */
    @Override
    public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
        AccessControlContext acc = null;

        if (System.getSecurityManager() != null &&
                (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                        bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                        bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
            acc = this.applicationContext.getBeanFactory().getAccessControlContext();
        }

        if (acc != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                    invokeAwareInterfaces(bean);
                    return null;
                }
            }, acc);
        }
        else {
            // 直奔重点,invoke这些Aware接口
            invokeAwareInterfaces(bean);
        }

        return bean;
    }

    private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof EnvironmentAware) {
                ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
            }
            if (bean instanceof EmbeddedValueResolverAware) {
                ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(
                        new EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
            }
            if (bean instanceof ResourceLoaderAware) {
                ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
            }
            if (bean instanceof ApplicationEventPublisherAware) {
                ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
            }
            if (bean instanceof MessageSourceAware) {
                ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
            }
            if (bean instanceof ApplicationContextAware) {
                ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
            }
        }
    }
    
    /**
     * 初始化之后就没有做其他操作了
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        return bean;
    }


}

自定义BeanPostProcessor

当然,每个人都可以自己写一个BeanPostProcessor的实现类。

不过写完之后注意要在Spring配置文件中配置一下。具体操作:

http://blog.csdn.net/caihaijiang/article/details/35552859

InitializingBean、init-method和@PostConstruct

这个两个东西,其实都是做一件事,就是在bean的初始化阶段做一些其他的操作。

比如,在有些情况下,某个业务对象实例化完成后,还不能处于可以使用状态。这个时候就可以让该业务对象实现该接口,并在方法afterPropertiesSet()中完成对该业务对象的后续处理。

以上这段文字是摘抄下来的,但是我真的想不到,到底为什么要这样操作,你说要改变初始化的状态,那在一开始初始化时直接改成那个状态不就可以了吗?为什么要在这里做变化?不懂。但是操作就是,在bean初始化阶段做操作。

这种操作,有三种方式来做InitializingBean、init-method和@PostConstruct。

InitializingBean

这是一个接口,只有一个方法。

public interface InitializingBean {

    void afterPropertiesSet() throws Exception;

}

如果一个bean想要在初始化阶段做操作,第一种方法就是实现这个接口

public Person implements InitializingBean {
    void afterPropertiesSet() throws Exception{
        System.out.println(" 初始化阶段操作 ")
    }
}

但是这种方式,其实还是会有点儿问题,这个对象和Spring的耦合度比较高。如果想使这个耦合度比较低,那么就用其他的两种方法了。

init-method

用一个例子,就能很好的把这个东西说清楚。

Person

class Person{
    ...
    void eat(){
        System.out.println("I am eating...");
    }
}

beans.xml

<beans> 
    <bean id="person" class="Person" .
    init-method="eat">
</bean>
...
</beans>

到时候实例化Person的时候,就会调用这个eat方法了。

@PostConstruct

其实这个注解和init-method是一样的。

person

class Person{
    ...
    @PostContruct
    void eat(){
        System.out.println("I am eating...");
    }
}

DisposableBean、destroy-method和@PreDestroy

在Bean销毁之前肯定也可以做些操作,这三者的特点和用法,其实都和初始化那部分差不多。不同的地方在下面这部分代码处体现。

Person

class Person{
     ...
    @PostContruct
    void eat(){
        System.out.println("I am eating...");
    }
    
    @PreDestroy
    void sleep(){
        System.out.println("I will go to sleep...");
    }
}

Main

class Main{
    public static void main(String [] args){
        ApplicationContext ac=new ClasspathXmlApplicationContext("beans.xml");
        Person person = (Person) ac.getBean("person");
        // 不一样之处,销毁时要调用,不然没人知道你什么不要。

        person.sleep();
    }   

beans.xml

<beans>
    <bean id="person" class="Person" >
    ...
    </bean>
</beans>

总结

这一小节和上一节应该是一个部分。本小节这要写的是BeanFactory的实例化的过程,当然在举例子的时候,还用到了ApplicationContext,但是总的来说并没有仔细的说ApplicationContext不同的高级特别,这部分内容,将会在下节做出阐述。

参考

http://blog.csdn.net/topwqp/article/details/8681497
http://blog.csdn.net/topwqp/article/details/8681497
http://www.cnblogs.com/sishang/p/6576665.html
http://blog.csdn.net/ikaraide/article/details/24180641
http://zhukunrong.iteye.com/blog/1929171
http://blog.csdn.net/shuangyue/article/details/8585736
http://997004049-qq-com.iteye.com/blog/1729793
http://www.cnblogs.com/liunanjava/p/4401089.html

目录
相关文章
|
8月前
|
搜索推荐 JavaScript Java
基于springboot的儿童家长教育能力提升学习系统
本系统聚焦儿童家长教育能力提升,针对家庭教育中理念混乱、时间不足、个性化服务缺失等问题,构建科学、系统、个性化的在线学习平台。融合Spring Boot、Vue等先进技术,整合优质教育资源,提供高效便捷的学习路径,助力家长掌握科学育儿方法,促进儿童全面健康发展,推动家庭和谐与社会进步。
|
XML Java 测试技术
Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)
Spring 第三节 IOC——基于注解配置和管理Bean 万字详解!
1029 26
|
监控 Java 应用服务中间件
微服务——SpringBoot使用归纳——为什么学习Spring Boot
本文主要探讨为什么学习Spring Boot。从Spring官方定位来看,Spring Boot旨在快速启动和运行项目,简化配置与编码。其优点包括:1) 良好的基因,继承了Spring框架的优点;2) 简化编码,通过starter依赖减少手动配置;3) 简化配置,采用Java Config方式替代繁琐的XML配置;4) 简化部署,内嵌Tomcat支持一键式启动;5) 简化监控,提供运行期性能参数获取功能。此外,从未来发展趋势看,微服务架构逐渐成为主流,而Spring Boot作为官方推荐技术,与Spring Cloud配合使用,将成为未来发展的重要方向。
567 0
微服务——SpringBoot使用归纳——为什么学习Spring Boot
|
8月前
|
XML Java 测试技术
《深入理解Spring》:IoC容器核心原理与实战
Spring IoC通过控制反转与依赖注入实现对象间的解耦,由容器统一管理Bean的生命周期与依赖关系。支持XML、注解和Java配置三种方式,结合作用域、条件化配置与循环依赖处理等机制,提升应用的可维护性与可测试性,是现代Java开发的核心基石。
|
12月前
|
XML 人工智能 Java
Spring IOC 到底是什么?
IOC(控制反转)是一种设计思想,主要用于解耦代码,简化依赖管理。其核心是将对象的创建和管理交给容器处理,而非由程序直接硬编码实现。通过IOC,开发者无需手动new对象,而是由框架负责实例化、装配和管理依赖对象。常见应用如Spring框架中的BeanFactory和ApplicationContext,它们实现了依赖注入和动态管理功能,提升了代码的灵活性与可维护性。
287 1
|
安全 Java 数据库
Spring Boot 框架深入学习示例教程详解
本教程深入讲解Spring Boot框架,先介绍其基础概念与优势,如自动配置、独立运行等。通过搭建项目、配置数据库等步骤展示技术方案,并结合RESTful API开发实例帮助学习。内容涵盖环境搭建、核心组件应用(Spring MVC、Spring Data JPA、Spring Security)及示例项目——在线书店系统,助你掌握Spring Boot开发全流程。代码资源可从[链接](https://pan.quark.cn/s/14fcf913bae6)获取。
1997 3
|
XML Java 数据格式
Spring IoC容器的设计与实现
Spring 是一个功能强大且模块化的 Java 开发框架,其核心架构围绕 IoC 容器、AOP、数据访问与集成、Web 层支持等展开。其中,`BeanFactory` 和 `ApplicationContext` 是 Spring 容器的核心组件,分别定位为基础容器和高级容器,前者提供轻量级的 Bean 管理,后者扩展了事件发布、国际化等功能。
371 18
|
Java Spring
Spring框架的学习与应用
总的来说,Spring框架是Java开发中的一把强大的工具。通过理解其核心概念,通过实践来学习和掌握,你可以充分利用Spring框架的强大功能,提高你的开发效率和代码质量。
321 20
|
XML Java 数据格式
【SpringFramework】Spring IoC-基于XML的实现
本文主要讲解SpringFramework中IoC和DI相关概念,及基于XML的实现方式。
358 69
|
XML Java 数据格式
京东一面:spring ioc容器本质是什么? ioc容器启动的步骤有哪些?
京东一面:spring ioc容器本质是什么? ioc容器启动的步骤有哪些?