• 每日总结之Spring


    可以先看一下大纲https://snailclimb.gitee.io/javaguide/#/docs/system-design/framework/spring/Spring%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E6%80%BB%E7%BB%93

    或者去开发手册:http://shouce.jb51.net/spring/

    或者教程网站:http://c.biancheng.net/view/4282.html

    了解清楚再来看下面问题。

    Bean的实例化?

    答:

    从本质上来说,bean定义描述了如何创建一个或多个对象实例。当需要的时候, 容器会从bean定义列表中取得一个指定的bean定义,并根据bean定义里面的配置元数据 使用反射机制来创建(或取得)一个实际的对象。

    当采用XML描述配置元数据时,将通过<bean/>元素的 class属性来指定实例化对象的类型。class 属性 (对应BeanDefinition实例的 Class属性)通常是必须的(不过也有两种例外的情形,见 Section 3.2.3.2.3, “使用实例工厂方法实例化”和 Section 3.6, “bean定义的继承”)。class属性主要有两种用途 :在大多数情况下,容器将直接通过反射调用指定类的构造器来创建bean(这有点类似于 在Java代码中使用new操作符);在极少数情况下,容器将调用 类的静态工厂方法来创建bean实例,class 属性将用来指定实际具有静态工厂方法的类(至于调用静态工厂 方法创建的对象类型是当前class还是其他的class则无关紧要)。

    首先介绍出BeanDefintion这个概念

    现如今,我们一般获取对象的方式有两种,一种是手动直接 new;另一种是交给 Spring 管理,Spring 将管理的对象称之为 Bean,容器会先实例化 Bean,然后自动注入,实例化的过程就需要依赖 BeanDefinition。

    BeanDefinition 用于保存 Bean 的相关信息,包括属性、构造方法参数、依赖的 Bean 名称及是否单例、延迟加载等,它是实例化 Bean 的原材料,Spring 就是根据 BeanDefinition 中的信息实例化 Bean。

    三种实例化方法:

      • 构造器的方式
      • 静态工厂方式
      • 实例化工厂方式

     但是这只是实例化并不是创建

    !!!关于Spring bean的创建,其本质上还是一个对象的创建,既然是对象,一定要明白一点就是,一个完整的对象包含两部分:当前对象实例化和对象属性的实例化。!!!

     所以对象的实例化很简单,确也不是创建的全部步骤,但是参考下面的问题你就能大概了解整个创建了

    Spring的循环依赖?

    答:

    在Spring中,对象的实例化是通过反射实现的,而对象的属性则是在对象实例化之后通过一定的方式设置的。

    这个过程可以按照如下方式进行理解:

     理解这一个点之后,对于循环依赖的理解就已经帮助一大步了,我们这里以两个类A和B为例进行讲解,如下是A和B的声明

    @Component
    public class A {
      private B b;
      public void setB(B b) {
        this.b = b;
      }
    }
    @Component
    public class B {
      private A a;
      public void setA(A a) {
        this.a = a;
      }
    }

    可以看到,这里A和B中各自都以对方为自己的全局属性。这里首先需要说明的一点,Spring实例化bean是通过ApplicationContext.getBean()方法来进行的。

    如果要获取的对象依赖了另一个对象,那么其首先会创建当前对象,然后通过递归的调用ApplicationContext.getBean()方法来获取所依赖的对象,最后将获取到的对象注入到当前对象中。

    这里我们以上面的首先初始化A对象实例为例进行讲解。

    首先Spring尝试通过ApplicationContext.getBean()方法获取A对象的实例,由于Spring容器中还没有A对象实例,因而其会创建一个A对象

    然后发现其依赖了B对象,因而会尝试递归的通过ApplicationContext.getBean()方法获取B对象的实例

    但是Spring容器中此时也没有B对象的实例,因而其还是会先创建一个B对象的实例。

    读者需要注意这个时间点,此时A对象和B对象都已经创建了,并且保存在Spring容器中了,只不过A对象的属性b和B对象的属性a都还没有设置进去。

    在前面Spring创建B对象之后,Spring发现B对象依赖了属性A,因而还是会尝试递归的调用ApplicationContext.getBean()方法获取A对象的实例

    因为Spring中已经有一个A对象的实例,虽然只是半成品(其属性b还未初始化),但其也还是目标bean,因而会将该A对象的实例返回。

    此时,B对象的属性a就设置进去了,然后还是ApplicationContext.getBean()方法递归的返回,也就是将B对象的实例返回,此时就会将该实例设置到A对象的属性b中。

    这个时候,注意A对象的属性b和B对象的属性a都已经设置了目标对象的实例了

    上面类似一个递归的过程。

     对于Spring处理循环依赖问题的方式,我们这里通过上面的流程图其实很容易就可以理解

      • Spring是通过递归的方式获取目标bean及其所依赖的bean的;
      • Spring实例化一个bean的时候,是分两步进行的,首先实例化目标bean,然后为其注入属性。

     

     上面看完了bean的启动流程,在来看看ioc的启动流程

     Sping事务?

    答:

    事务是逻辑处理原子性的保证手段,通过使用事务控制,可以极大的避免出现逻辑处理失败导致的脏数据等问题。

    事务最重要的两个特性,是事务的传播级别和数据隔离级别。传播级别定义的是事务的控制范围,事务隔离级别定义的是事务在数据库读写方面的控制范围。

    事务的7种传播级别,四种隔离级别

    Spring配置声明式事务:

    * 配置DataSource
    * 配置事务管理器
    * 事务的传播特性
    * 那些类那些方法使用事务

    Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。

    Spring BeanFactory和FactoryBean的区别?

    答:

    BeanFactory

    是一个接口,public interface BeanFactory,提供如下方法:

    • Object getBean(String name)
    • <T> T getBean(String name, Class<T> requiredType)
    • <T> T getBean(Class<T> requiredType)
    • Object getBean(String name, Object... args)
    • boolean containsBean(String name)
    • boolean isSingleton(String name)
    • boolean isPrototype(String name)
    • boolean isTypeMatch(String name, Class<?> targetType)
    • Class<?> getType(String name)
    • String[] getAliases(String name)

    在 Spring 中,BeanFactory是 IoC 容器的核心接口。它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。

    BeanFactory 提供的高级配置机制,使得管理任何性质的对象成为可能。
    ApplicationContextBeanFactory 的扩展,功能得到了进一步增强,比如更易与 Spring AOP 集成、消息资源处理(国际化处理)、事件传递及各种不同应用层的 context 实现(如针对 web 应用的WebApplicationContext)。

    用的比较多的 BeanFactory 的子类是 ClassPathXmlApplicationContext,这是 ApplicationContext接口的一个子类,ClassPathXmlApplicationContext从 xml 的配置文件中获取 bean 并且管理他们

    例如:

    public static void main(String[] args) throws Exception {
        BeanFactory bf = new ClassPathXmlApplicationContext("student.xml");
        Student studentBean = (Student) bf.getBean("studentBean");
    
        studentBean.print();
    }
    

    XML配置如下:

    <bean id="studentBean" class="advanced.Student">
        <property name="name" value="Tom"/>
        <property name="age" value="18"/>
    </bean>

    FactoryBean

    Spring 中为我们提供了两种类型的 bean,一种就是普通的 bean,我们通过 getBean(id) 方法获得是该 bean 的实际类型,另外还有一种 bean 是 FactoryBean,也就是工厂 bean,我们通过 getBean(id) 获得是该工厂所产生的 Bean 的实例,而不是该 FactoryBean 的实例。

    FactoryBean 是一个 Bean,实现了 FactoryBean 接口的类有能力改变 bean,FactoryBean 希望你实现了它之后返回一些内容,Spring 会按照这些内容去注册 bean。
    public interface FactoryBean<T>,提供如下方法:

    • T getObject()
    • Class<?> getObjectType()
    • boolean isSingleton()

    通常情况下,bean 无须自己实现工厂模式,Spring 容器担任工厂 角色;但少数情况下,容器中的 bean 本身就是工厂,作用是产生其他 bean 实例。由工厂 bean 产生的其他 bean 实例,不再由 Spring 容器产生,因此与普通 bean 的配置不同,不再需要提供 class 元素。

    示例:
    构造一个 FactoryBean 的实现:

    public class StudentFactoryBean implements FactoryBean<Student> {
        private String name;
        private int age;
    
        @Override
        public Student getObject() throws Exception {
            return new Student(name, age);
        }
    
        @Override
        public Class<?> getObjectType() {
            return Student.class;
        }
    
        /**
         * 工厂所管理的对象是否为单例的
         * 即如果该方法返回true,那么通过getObject()方法返回的对象都是同一个对象
         */
        @Override
        public boolean isSingleton() {
            return true;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    

    XML配置如下:

    <bean id="studentFactoryBean" class="spring.StudentFactoryBean">
        <property name="name" value="Tom"/>
        <property name="age" value="28"/>
    </bean>
    

    使用:

    public static void main(String[] args) throws Exception {
        BeanFactory bf = new ClassPathXmlApplicationContext("student.xml");
        Student studentBean = (Student) bf.getBean("studentFactoryBean");
    
        studentBean.print();
    }

    Q1:IoC 是什么?

    Q2:IoC 容器初始化过程?


    Q3:依赖注入的实现方法有哪些?


    Q4:依赖注入的相关注解?


    Q5:依赖注入的过程?


    Q6:Bean 的生命周期?


    Q7:Bean 的作用范围?


    Q8:如何通过 XML 方式创建 Bean?


    Q9:如何通过注解创建 Bean?


    Q10:如何通过注解配置文件?


    Q11:BeanFactory、FactoryBean 和 ApplicationContext 的区别?


    Spring AOP

    Q1:AOP 是什么?


    Q2:AOP 的相关注解有哪些?

    Q3:AOP 的相关术语有什么?


    Q4:AOP 的过程?

  • 相关阅读:
    Microsoft .NET Framework 2.0实现发送邮件(Email)总结
    Microsoft .NET Framework 2.0对文件传输协议(FTP)操作(上传,下载,新建,删除,FTP间传送文件等)实现汇总
    抽象类
    WingIDE 单步调试 Uliweb Python 代码
    Android 4.0 SDK的离线方式安装
    .NET 3.5 中WCF客户端代理性能改进以及最佳实践
    在linux上部署Redmine
    认识jQuery mobile 框架,资源,书籍
    如何使用搜索技巧来成为一名高效的程序员
    Management Console 工具管理类软件通用开发框架(开放源码)
  • 原文地址:https://www.cnblogs.com/yangj-Blog/p/14547357.html
Copyright © 2020-2023  润新知