Java面试 (5) :SSM(Spring框架、Spring MVC、MyBatis…)

Java面试——SSM基础知识:Spring框架、Spring MVC、MyBatis…

在这里插入图片描述

在这里插入图片描述


1 String框架

1.1 IOC和DI

  • 控制反转IOC):Spring容器使用工厂模式来创建所需要的对象,使得不需要自己去创建,直接调用Spring提供的对象即可。
  • 依赖注入DI):Spring使用Java Bean对象的setter方法或者带参数的构造方法,在创建所需对象时将其属性自动设为所需要的值。
    1. 构造器依赖注入:容器触发一个类的构造器。该类有一系列参数,每个参数代表一个对其他类的依赖。
    2. Setter方法注入:容器通过调用无参构造器或无参static工厂方法实例化bean之后,调用该bean的setter方法。

1.2 Bean

1.2.1 作用域

Spring框架支持以下五种bean的作用域:

  1. singleton:bean在每个Spring IOC容器中只有一个实例。
  2. prototype:一个bean的定义可以有多个实例。
  3. request:每次http请求都会创建一个bean,该作用域仅在基于web的Spring ApplicationContext情形下有效。
  4. session:在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
  5. application:属于应用程序域。应用程序启动时bean创建,应用程序销毁时bean 销毁。该作用域仅在基于web的ServletContext。

1.2.2 自动装配模式

Spring的自动装配功能:无须在Spring配置文件中描述Java Bean之间的依赖关系(如配置<property><constructor-arg>)。

自动装配模式:

  1. no:Spring框架的默认设置,在该设置下自动装配关闭。开发者需要自行在bean定义中用标签明确的设置依赖关系 。
  2. byName:该选项可根据bean名称设置依赖关系 。 当向一个bean中自动装配一个属性时,容器将根据bean的名称自动在在配置文件中查询一个匹配的bean。 若找到则装配这个属性,若没找到则报错。
  3. byType:该选项可以根据bean类型设置依赖关系 。 当向一个bean中自动装配一个属性时,容器将根据 bean的类型自动在在配置文件中查询一个匹配的bean。 若找到则装配这个属性,若没找到则报错。
  4. constructor:构造器的自动装配和byType模式类似,但仅适用于与有构造器相同参数的bean。若在容器中没有找到与构造器参数类型一致的bean,则会抛出异常 。
  5. default:该模式自动探测使用构造器自动装配或byType自动装配。 首先会尝试找合适的带参数的构造器,若找到则用构造器自动装配;若在bean内部没有找到相应的构造器或无参构造器,容器就会自动选择byType自动装配方式 。

【例】如下注入

在这里插入图片描述
可以改造为
在这里插入图片描述

1.2.3 生命周期

在这里插入图片描述

1.2.3.1 doGetBean()源码

Spring框架在创建的bean时都会调用AbstractBeanFactory类中的doGetBean()方法。

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
        @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
   
    // 获取beanName。有三种形式:原始的beanName、加了&、别名
    final String beanName = transformedBeanName(name);
    Object bean;

    // Eagerly check singleton cache for manually registered singletons.
    // 是否已经创建了
    Object sharedInstance = getSingleton(beanName);
    // 已经创建了——若没有构造参数,进入该方法;如果有构造参数,往else走,即不获取bean,而直接创建bean
    if (sharedInstance != null && args == null) {
   
        if (logger.isTraceEnabled()) {
   
            if (isSingletonCurrentlyInCreation(beanName)) {
   
                logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                        "' that is not fully initialized yet - a consequence of a circular reference");
            } else {
   
                logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
            }
        }
        // 若为普通bean,直接返回;若为FactoryBean,返回其getObject
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    } else {
   
        // Fail if we're already creating this bean instance:
        // We're assumably within a circular reference.
        // 没创建过bean或者是多例的情况或者有参数的情况
        // 创建过Prototype的bean会循环引用。需抛出异常,单例才尝试解决循环依赖的问题
        if (isPrototypeCurrentlyInCreation(beanName)) {
   
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // Check if bean definition exists in this factory.
        BeanFactory parentBeanFactory = getParentBeanFactory();
        // 父容器存在,本地没有当前beanName,从父容器取
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
   
            // Not found -> check parent.
            // 处理后,如果是加&,就补上&
            String nameToLookup = originalBeanName(name);
            if (parentBeanFactory instanceof AbstractBeanFactory) {
   
                return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                        nameToLookup, requiredType, args, typeCheckOnly);
            } else if (args != null) {
   
                // Delegation to parent with explicit args.
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            } else if (requiredType != null) {
   
                // No args -> delegate to standard getBean method.
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            } else {
   
                return (T) parentBeanFactory.getBean(nameToLookup);
            }
        }

        if (!typeCheckOnly) {
   
            // typeCheckOnly为false,将beanName放入alreadyCreated中
            markBeanAsCreated(beanName);
        }

        try {
   
            // 获取BeanDefinition
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            // 抽象类检查
            checkMergedBeanDefinition(mbd, beanName, args);

            // Guarantee initialization of beans that the current bean depends on.
            // 如果有依赖的情况,先初始化依赖的bean
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
   
                for (String dep : dependsOn) {
   
                    // 检查是否循环依赖,a依赖b,b依赖a。包括传递的依赖,比如a依赖b,b依赖c,c依赖a
                    if (isDependent(beanName, dep)) {
   
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }
                    // 注册依赖关系
                    registerDependentBean(dep, beanName);
                    try {
   
                        // 初始化依赖的bean
                        getBean(dep);
                    } catch (NoSuchBeanDefinitionException ex) {
   
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Akira37

💰unneeded

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值