Spring相关

Spring相关的一些问题

Posted by ZBX on April 8, 2020

测试life cycle

interfaces:

  • ApplicationContextAware: This will ask you to implement the setApplicationContext method
  • BeanNameAware: This will tell you to implement the setBeanName method•
  • InitializingBean: This will force you to implement the afterPropertiesSet() method•
  • BeanFactoryAware: This will request you to implement the setBeanFactory method•
  • BeanPostProcessor: This needs you to implementthe postProcessBeforeInitialization and postProcessAfterInitialization methods•
  • DisposableBean: This needs to implement the destroy() method

AOP概念

Join point: This is a well-defined point during the execution of your application. You can insert additional logic at join points.

Advice: This is the code that is executed at a specific join point.

Pointcut: This is a collection of join points to execute an advice

Aspect: This defines the implementation of the cross-cutting concern. An aspect is the combination of advice and pointcuts.

Weaving: This is the process of applying aspects into the code at the appropriate join points.

ApplicationContext

ApplicatonContext 父接口

  • BeanFactory:Spring管理Bean的顶层接口,简易版的Spring容器,其子类HierarchicalBeanFactory是一个具有层级关系的BeanFactory,ListableBeanFactory实现了枚举方法可以列举出当前BeanFactory中所有的bean对象而不必根据name一个个的获取。
  • ApplicationEventPublisher:Spring事件发布者
  • ResourceLoader:Spring资源加载的顶级接口
  • MessageSource:国际化功能
  • EnvironmentCapable:提供当前系统环境Environment组件。

ApplicationContext子接口

两个子类:和ConfigurableApplicationContext

  • WebApplicationContext
    • 该接口只有一个#getServletContext()方法,用于给Servlet提供上下文信息。
  • ConfigurableApplicationContext
    • ConfigurableWebApplicationContext 派生WebApplicationContext和ConfigureableContext。提供了一个可配置可管理的webApplicationContext,同时,该接口还提供了#setServletContext()方法

Spring 用到的设计模式

工厂设计模式

Spring使用工厂模式可以通过BeanFactoryApplicationContext创建bean对象。

单例设计模式

Spring 通过 ConcurrentHashMap 实现单例注册表的特殊方式实现单例模式。

代理模式

AOP

模板模式

模板方法模式是一种行为设计模式,它定义一个操作中算法的骨架,而将一些步骤延迟到之类中。模板方法使得之类可以不改一个算法的结构即可重定义该算法的某些特定步骤的实现方式。

Spring 中 jdbcTemplatehibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。

观察者模式

适配器模式

装饰者模式

@Component,@Repository, @Service,@Bean的区别

  1. @Component注解表明一个类会作为组件类,并告知Spring要为这个类创建bean。
  2. @Bean注解告诉Spring这个方法将会返回一个对象,这个对象要注册为Spring应用上下文中的bean。通常方法体中包含了最终产生bean实例的逻辑。
  3. @Component@Bean都是用来注册Bean并装配到Spring容器中,但是Bean比Component的自定义性更强。可以实现一些Component实现不了的自定义加载类。
  4. @Component, @Service, @Controller, @Repository是spring注解,注解后可以被spring框架所扫描并注入到spring容器来进行管理 @Component是通用注解,其他三个注解是这个注解的拓展,并且具有了特定的功能 @Repository注解在持久层中,具有将数据库操作抛出的原生异常翻译转化为spring的持久层异常的功能。 @Controller层是spring-mvc的注解,具有将请求进行转发,重定向的功能。 @Service层是业务逻辑层注解,这个注解只是标注该类处于业务逻辑层。

  5. @Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。

SpringMvc工作流程是什么?

image-20240303224906719

image-20240303231245289

spring事务什么时候会失效?

image-20240303232534921

spring bean生命周期

image-20240303233322727

解决循环依赖

循环依赖其实就是循环引用,也就是两个或则两个以上的bean互相持有对方,最终形成闭环。

Spring的单例对象的初始化主要分为三步:

(1)createBeanInstance:实例化,其实也就是调用对象的构造方法实例化对象

(2)populateBean:填充属性,这一步主要是多bean的依赖属性进行填充

(3)initializeBean:调用spring xml中的init 方法。

循环依赖主要发生在(1)、(2)。

三级缓存

/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);

/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);

/** Cache of early singleton objects: bean name --> bean instance */
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);

这三级缓存分别指: singletonFactories : 单例对象工厂的cache earlySingletonObjects :提前暴光的单例对象的Cache singletonObjects:单例对象的cache

在创建bean的时候,会首先从cache中获取这个bean,这个缓存就是sigletonObjects。主要的调用方法是:

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject = this.singletonObjects.get(beanName);
    //isSingletonCurrentlyInCreation()判断当前单例bean是否正在创建中
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            singletonObject = this.earlySingletonObjects.get(beanName);
            //allowEarlyReference 是否允许从singletonFactories中通过getObject拿到对象
            if (singletonObject == null && allowEarlyReference) {
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    //从singletonFactories中移除,并放入earlySingletonObjects中。
                    //其实也就是从三级缓存移动到了二级缓存
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

检测循环依赖的过程如下:

  • A 创建过程中需要 B,于是 A 将自己放到三级缓里面 ,去实例化 B

  • B 实例化的时候发现需要 A,于是 B 先查一级缓存,没有,再查二级缓存,还是没有,再查三级缓存,找到了!

    • 然后把三级缓存里面的这个 A 放到二级缓存里面,并删除三级缓存里面的 A
    • B 顺利初始化完毕,将自己放到一级缓存里面(此时B里面的A依然是创建中状态)
  • 然后回来接着创建 A,此时 B 已经创建结束,直接从一级缓存里面拿到 B ,然后完成创建,并将自己放到一级缓存里面