Spring简述

1、概述:

此篇博文,和后续几篇博文,码字之前,有点惶恐,恐言语不当,误彼误己,思后还是决定写,一是为了整理记忆,二是把自己所想所悟写出,让大家指正,共同进步。此篇博文,主要写Spring,后续会写SpringMvc、SpringBoot、SpringCloud。

Spring核心可分为以下几点:

  1. 依赖注入,控制反转;
  2. 生命周期;
  3. aop;
  4. 循环依赖;

注:此篇文章中的代码是基于Sprng5.0注解开发,非xml装配bean,另外工程是基于eclipse 简单maven工程。

2、依赖注入,控制反转:

在述之前,我们先简单认识一下Spring,Spring本质就是对java对象管理,它会将java对象放在一个线程安全的hashmap里,key就是对象的名字,如:

 @Bean
 public User user() {

        User user = new User();

        user .setName("sd");
        user .setUserId(100);

        return user ;
  }

Map hashMap = new ConcurrentHashMap<String,Object>();                  

hashMap.put("user", user() );

hashMap可理解为Spring的容器,看以下内容脑里一定要有这个存储模型。

我经常面试时,谈及Spring,都会问面试者对这8个字(依赖注入,控制反转)理解,几乎全是这样回答,bean方式注入Spring容器,无需java new去创建对象,暂不论回答对错。

现在来拆分这个8个字,依赖,即我写的代码,要去依赖Spring提供的bean对象。注入,即将依赖的bean对象注入到Spring容器中。控制,即我写的代码,要去控制Spring中依赖bean对象的实现逻辑,到了这里发现没有,我写的代码没有去实现具体逻辑,而是反过来去控制Spring中依赖bean的实现逻辑,这就是反转。

上面所书有点绕,来一个简单又明朗的!就是我写的代码要去依赖Spring容器,从中获取对象,而这个对象实现的逻辑,要按我的逻辑去实现编码,说白了就是我不想去实现,你帮我实现就行,我要你就给我。

从Spring容器中获得bean对象很简单,无非这样 User user = hashMap.get("user")。难的是如何去控制bean对象实现逻辑,java是面向对象语言,有封装、继承、多态三大特性,继承可以继承接口实现逻辑,接口本质实现编码约定,这里的约定,可理解为我让你实现我需要的逻辑,多态用于运行时动态链编,父类可见于子类的实现。整过程说白了,就是我定义接口约定,让你实现,实现好了以后,再注入到Spring容器,并为其取一个我们之间约定好的名字,然后我使用时通过名字找到bean对象,赋值于接口变量,实现调用。

例如:用mybatis访问数据库,配置数据源时,无需关心连结的数据库是mysql,还是oracle,只需要配置指定驱动包就行,如:spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver或spring.datasource.driver-class-name=com.mysql.jdbc.Driver 。也不关心使用的连结池,是阿里的也吧,是c3p0也好,mybatis只需要定义一个数据源接口(datasource),制定好规范,让别人实现,mybatis使用时从Spring容器中取出对象,赋值给接口变量,实现调用就行。下面是SprinBoot直观的配制:

Mysql:

spring.datasource.min-idle=5
spring.datasource.max-idle=10
spring.datasource.max-active=15
spring.datasource.username=test
spring.datasource.password=test
spring.datasource.initial-size=5
spring.datasource.max-wait=10000
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql://192.168.106.142:3306/?characterEncoding=utf-8&serverTimezone=GMT%2B8

Oracle:

spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.password=test
spring.datasource.url=jdbc:oracle:thin:@192.168.106.142:1521:test
spring.datasource.username=dev
spring.datasource.initial-size=8
spring.datasource.max-idle=10
spring.datasource.max-wait=30000
spring.datasource.min-idle=8
spring.datasource.max-active=20

再来一个Xml bean注入,更直观:

<bean id="dataSource1" class="com.alibaba.druid.pool.DruidDataSource"
        destroy-method="close">
        <!-- 数据库基本信息配置 -->
        <property name="url" value="${url1}" />
        <property name="username" value="${username1}" />
        <property name="password" value="${password1}" />
        <property name="driverClassName" value="${driverClassName}" />
        <property name="filters" value="${filters}" />
        <!-- 最大并发连接数 -->
        <property name="maxActive" value="${maxActive}" />
        <!-- 初始化连接数量 -->
        <property name="initialSize" value="${initialSize}" />
        <!-- 配置获取连接等待超时的时间 -->
        <property name="maxWait" value="${maxWait}" />
        <!-- 最小空闲连接数 -->
        <property name="minIdle" value="${minIdle}" />
        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}" />
        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="${minEvictableIdleTimeMillis}" />
        <property name="validationQuery" value="${validationQuery}" />
        <property name="testWhileIdle" value="${testWhileIdle}" />
        <property name="testOnBorrow" value="${testOnBorrow}" />
        <property name="testOnReturn" value="${testOnReturn}" />
        <property name="maxOpenPreparedStatements" value="${maxOpenPreparedStatements}" />
        <!-- 打开 removeAbandoned 功能 -->
        <property name="removeAbandoned" value="${removeAbandoned}" />
        <!-- 1800 秒,也就是 30 分钟 -->
        <property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" />
        <!-- 关闭 abanded 连接时输出错误日志 -->
        <property name="logAbandoned" value="${logAbandoned}" />
    </bean>

那依赖注入,控制反转,到底有什么好处,我认为核心是解藕,就是我不关心具体的实现,我只知道要实现什么,告诉别人给我实现就好,然后通过Spring在藕在一起,并且具体实现是可插拔的(接口和多态),因为实现者可以有多个,我觉得那个好,我就用那个。

另外就是要有容器的思想,就是我们开发时,所需对象全部注入到Spring容器,即放入线程安全的hash里,统一管理。

2、生命周期:

我这里写的生命周期,可能与其它笔者不一样,仅是我的理解总结。

一是指bean驻留内存的生命周期,即bean在Spring容器进程生命周期内,会不会被gc回收。二是指bean从无到有、到初使化(其实主要谈这里)、再到注入Spring容器的生命周期。

先谈一,我们都知道, Spring容器中bean有5种作用域,分别是:
1、singleton 单例模式,全局有且仅有一个实例;
2、prototype 原型模式,每次获取bean都会产生一个新的对象;
3、request 每次请求都会产生一个新的对象,并且bean对象只对当前http请求有效;
4、session,会session会话周期一样;
5、global session 每个全局的HttpSession对应一个实例;

后三种主要是http请求相关,这里不细说,也很少用。singleton创建后会长驻内存,且Spring容器中只能有一个唯一(bean id一样)对象,prototype 创建后也会长驻内存,但每次从Spring容器获取都会产生一个新的对象,可以看出singleton是非线程安全,prototype是线程安全。Spring容器即是一个ConcurrentHashMap集合对象,如果其生命周期不能与进程寿终正寝,就不能谈进程,这里要强调一下。可以用@Scope注解控制作用域,如:@Scope("singleton")。

singleton还有一个知识点,即Spring bean对象的创建时机,分为懒汉式和饿汉式,赖汉式用到的时候再创建,饿汉式Spring容器一运行加载时就创建,默认是饿汉式。可以用Lazy控制加载方式,如:@Lazy(true)就是懒汉式。

现在来谈二,即是bean创建注入到Spring容器的过程,其实这里没什么好写的,总结下来就是:

1、反射创建bean对象;

2、调用set方法设置属性值(如果设置了);

3、调用对象继承的接口方法(如果实现了,如:ApplicationContextAware接口,主要是用来获取ApplicationContext),说白  了就是bean对象注入Spring容器过程中,Spring检查是否实现了约定接口,如果实现了就调用,目的实现一些自定义逻辑和回送一些你所需信息。代码如:

public class GetApplicationContext implements ApplicationContextAware{

    private static ApplicationContext applicationContext = null;

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("setApplicationContext");
        GetApplicationContext.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext() {
        return GetApplicationContext.applicationContext;
    }
}

@Bean
public GetApplicationContext getApplicationContext() {
    return new GetApplicationContext();
}

4、调用前置处理器方法、再调用initMethod方法、再调用后置处理器方法,代码如:

public class TestBeanPostProcessor implements BeanPostProcessor{

    //前置处理器
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization" + "  "  + beanName);
        return bean;
    }
    
    //后置处理器
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization" + "  "  + beanName);
        return bean;
    }
    
    private void initMethod() {
        System.out.println("call initMethod");
    }
}

@Bean(initMethod = "initMethod")
public TestBeanPostProcessor testBeanPostProcessor() {
    return new TestBeanPostProcessor();
}

这里我们可以看到前置和后置处理器方法,对initMethod方法进行前后拦截,这也是aop的思想(后续会说),我们先记住后置处理器方法(aop代理对象和被代理对象是在这里实现绑定)。我们是实现BeanPostProcessor接口实现前置和后置处理器方法。

5、注入容器,使用与销毁(如果注解了@Bean(destroyMethod = "destroyMethod"),将会被调用);

以上代码不完整,如果要可加我的联系方式。

4、aop:

aop其实是一种编程思想,编码发展过程可简述为,过程化开发(早期汇编和C语言时代),再到面向对象开发(c++、java、c#),最后到面向切面(aop),aop本质是无感知(动态链编)对实现的代码进行拦截,如:mybatis访问数据库时的事务注解,用于事务开启,提交或回滚。

aop有前置、后置、环绕、运行、异常5类切面通知,如果我们同时开启,运行和异常将是互斥的,也就是说如果发生异常,运行通知不会执行,致于其它切面通知执行顺序(切面通知调用执行顺序,用到了责任链设计模式。),请运行代码自行总结,代码如下:

1、基于eclipse创建一个简单的maven工程,并在pom.xml引入所需依赖,如:

<dependencies> 

    <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.0.RELEASE</version>
        </dependency>

        <!-- aop -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.2</version>
        </dependency>

</dependencies>

2、定义切面类,指定切入口(即扫包指定),开启切面通知(前置、后置、环绕、运行、异常),代码如下:

package com.springaop.testaop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LogAop {

    @Pointcut("execution (* com.springaop.serviceaop..*.*(..))")
    public void logAop() {

    }

    @Before("logAop()")
    public void doBefore(JoinPoint joinPoint) {
        System.out.println("before + 前置通知");
    }

    @After("logAop()")
    public void doAfter(JoinPoint joinPoint) {
        System.out.println("after + 后置通知");
    }

    @AfterReturning("logAop()")
    public void afterReturning(JoinPoint joinPoint) {
        System.out.println("afterReturning + 运行通知");
    }

    @AfterThrowing("logAop()")
    public void afterThrowing(JoinPoint joinPoint) {
        System.out.println("afterThrowing + 异常通知");
    }
    
    @Around("logAop()")
    public void doAround(ProceedingJoinPoint joinPoint)throws Throwable{
        System.out.println("doAround + 环绕通知(s)");
        joinPoint.proceed();
        System.out.println("doAround + 环绕通知(e)");
    }
}

3、定义实现层,用于被aop切面测试,代码如:

package com.springaop.serviceaop;

import org.springframework.stereotype.Component;

@Component
public class LogAopService {

public void testAop() throws Exception {
        System.out.println("test testAop");
        int i = 10;
        //i = 1 / 0;  //用于测试异常切面通知
        System.out.println(i);
    }
}

4、定义Spring注解类( @Configuration ),注解类相当于早期的xml注解,本质就是将对象注入到Spring容器,代码如下:

package com.springaop.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;

import com.springaop.testaop.LogAop;

@Configuration
@EnableAspectJAutoProxy
@ComponentScan({"com.springaop.serviceaop","com.springaop.testaop"})
public class MySpringAop {
}

相关注解说明:

@Component:将定义类注入Spring容器;
@EnableAspectJAutoProxy:开启aop;
@Aspect:定义切面类;
@Pointcut:定义切入口;
@ComponentScan:扫包将类注入Spring容器;

5、定义Spring容器启动类,测试aop,代码如下:

package com.springaop;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.springaop.config.MySpringAop;
import com.springaop.serviceaop.LogAopService;

public class Test1 {

    private static AnnotationConfigApplicationContext applicationContext;
    
    public static void main(String[] args) {
        //通过java类注解方式,启动spring容器。
        applicationContext = new AnnotationConfigApplicationContext(MySpringAop.class);
        
        if (null == applicationContext){
            System.out.println("start spring fail");
            return;
        }
        
        LogAopService logAopService = applicationContext.getBean("logAopService", LogAopService.class);
        
        try {
            logAopService.testAop();
        } catch (Exception e) {
            e.printStackTrace();
        }


        System.out.println("over");
    }
}

以上代码自行运行测试,现在我们来思考Spring aop怎么实现动态切入?

其实Spring是在bean对象生成时,后置处理器方法里创建代理对象实现切入,而这个切入的逻辑,是@EnableAspectJAutoProxy这个注解完成的,该注解内容如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
    boolean proxyTargetClass() default false;
    boolean exposeProxy() default false;

}

@Import(AspectJAutoProxyRegistrar.class),@Import将会把AspectJAutoProxyRegistrar注入到Spring容器,完成动态代理对象的创建,当bean容器注入Spring容器时,如果被@Pointcut切入(扫包),就会在后置处理器方法里完成切入,实现无感知拦截。

Spring创建代理对象(即实现aop)有两种方式,如果被代理类有实现接口就用jdk动态代理,如果没有实现就用cglib动态代理。

最后总结一下,SpringAop 综合运用cglib和jdk动态代理,实现代理对象创建,如果被代理类有实现接口就用jdk动态代理,如果没有实现就用cglib动态代理,并在后置处理器调用AspectJAutoProxyRegistrar方法完成代理对象与被代理对象绑定,实现切面。

5、循环依赖:

循环依赖其实也没什么好写的,很多博文或者其它,我感觉都写得太繁杂了,无非事注入Spring的Bean对象,出现相互依赖创建,即我中有你,你中有我,并且不是单例模式。

如:

public class A{
    @Autowired
    private B b;
    .....
}

public class B{
    @Autowired
    private A a;
    .....
}

@Configuration
public class MySpringConfig {
    @Bean
    @Scope("prototype")
    public A a() {
        return new A();
    }

       @Bean
    @Scope("prototype")
    public B b() {
        return new B();
    }
}

那如何解决,使用单例,从逻辑层绕开,最后可能有人会问单例是如何解决循环依赖,什么是Spring三级缓存?

先来引入一个概念,完整对象和非完整对象,完整对象是指对象创建了,所有属性已经赋值,非完整对象是指对象创建了,属性没有赋值。如代码:

HashMap<Object,Object> objectHashMap = new HashMap<Object,Object>();

objectHashMap.put("A", new A());
objectHashMap.put("B", new B());

A a = (A)objectHashMap.get("A");
B b = (B)objectHashMap.get("B");

a.SetB(b);  //a未赋值前是非完整对象
b.SetA(a);  //b未赋值前是非完整对象

其实上面代码就是Spring解决单例循环依赖的方式,Spring用的是递归调用函数的方式。

有了上面的概念,我们来看Spring使用三级缓存解决单例循环依赖。

Spring使用的三级缓存集合。

private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));

singletonObjects:是一级缓存,缓存完整对象,即创建成功的对象,并且所有属性已经赋值;
earlySingletonObjects:是二级缓存;
singletonFactories:是三级缓存;
singletonsCurrentlyInCreation:用来标记开始创建的对象;

核心代码请看中文注解就行。

//看代码入口函数,该函数完成bean的创建,代码在该类下:org.springframework.beans.factory.support.AbstractBeanFactory
    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

        final String beanName = transformedBeanName(name);
        Object bean;

        // 从缓存中获取对象,
        Object sharedInstance = getSingleton(beanName);
        
        if (sharedInstance != null && args == null) {
            if (logger.isDebugEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

        else {
            // 从缓存中没有获取到对象
            
            //判断是否是多例循环依赖,如果是抛出异常,所以Spring没有解决多例的循环依赖。
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // Check if bean definition exists in this factory.
            BeanFactory parentBeanFactory = getParentBeanFactory();
            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 {
                    // No args -> delegate to standard getBean method.
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }

            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }

            try {
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);

                // Guarantee initialization of beans that the current bean depends on.
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        registerDependentBean(dep, beanName);
                        getBean(dep);
                    }
                }

                // Create bean instance.
                if (mbd.isSingleton()) {
                    /*
                    我们创建对象是单例,因此将会走这里。
                    getSingleton(beanName, () -> {可理解为标记对象创建
                   */
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            //标记完了就去创建对象
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            // Explicitly remove instance from singleton cache: It might have been put there
                            // eagerly by the creation process, to allow for circular reference resolution.
                            // Also remove any beans that received a temporary reference to the bean.
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    Object prototypeInstance = null;
                    try {
                        beforePrototypeCreation(beanName);
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        afterPrototypeCreation(beanName);
                    }
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }

                else {
                    String scopeName = mbd.getScope();
                    final Scope scope = this.scopes.get(scopeName);
                    if (scope == null) {
                        throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                    }
                    try {
                        Object scopedInstance = scope.get(beanName, () -> {
                            beforePrototypeCreation(beanName);
                            try {
                                return createBean(beanName, mbd, args);
                            }
                            finally {
                                afterPrototypeCreation(beanName);
                            }
                        });
                        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    }
                    catch (IllegalStateException ex) {
                        throw new BeanCreationException(beanName,
                                "Scope '" + scopeName + "' is not active for the current thread; consider " +
                                "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                                ex);
                    }
                }
            }
            catch (BeansException ex) {
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }

        // Check if required type matches the type of the actual bean instance.
        if (requiredType != null && !requiredType.isInstance(bean)) {
            try {
                T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
                if (convertedBean == null) {
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
                return convertedBean;
            }
            catch (TypeMismatchException ex) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Failed to convert bean '" + name + "' to required type '" +
                            ClassUtils.getQualifiedName(requiredType) + "'", ex);
                }
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }
        return (T) bean;
    }

//从缓存中取象
protected Object getSingleton(String beanName, boolean allowEarlyReference) {

        //首先从一级缓存,取到直接返回。
        Object singletonObject = this.singletonObjects.get(beanName);
        
        /*isSingletonCurrentlyInCreation标识对象没有创建,如果对象开始创建了将会在singletonsCurrentlyInCreation中标记*/
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
            
                //一级缓存没有查询二级缓存,二级有就直接返回。
                singletonObject = this.earlySingletonObjects.get(beanName);
                
                if (singletonObject == null && allowEarlyReference) {
                
                    //二级缓存再没有,再查询三级缓存,三级缓存没有就返回空。
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    
                    if (singletonFactory != null) {
                        //三级有把其放入二级并返回。
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        
        return singletonObject;
    }
    
    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "Bean name must not be null");
        synchronized (this.singletonObjects) {
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                if (this.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException(beanName,
                            "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                            "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                }
                //标识该对象已经开始创建了
                beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<>();
                }
                try {
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                }
                catch (IllegalStateException ex) {
                    // Has the singleton object implicitly appeared in the meantime ->
                    // if yes, proceed with it since the exception indicates that state.
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        throw ex;
                    }
                }
                catch (BeanCreationException ex) {
                    if (recordSuppressedExceptions) {
                        for (Exception suppressedException : this.suppressedExceptions) {
                            ex.addRelatedCause(suppressedException);
                        }
                    }
                    throw ex;
                }
                finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
                    afterSingletonCreation(beanName);
                }
                if (newSingleton) {
                    //属性赋值成功以后(完整对象),最后把对象放放到一级缓存
                    addSingleton(beanName, singletonObject);
                }
            }
            return singletonObject;
        }
    }
    
    //标识该对象已经开始创建了
    protected void beforeSingletonCreation(String beanName) {
        if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }
    }
    
    //开始创建bean对象
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

        if (logger.isDebugEnabled()) {
            logger.debug("Creating instance of bean '" + beanName + "'");
        }
        RootBeanDefinition mbdToUse = mbd;

        // Make sure bean class is actually resolved at this point, and
        // clone the bean definition in case of a dynamically resolved Class
        // which cannot be stored in the shared merged bean definition.
        Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

        // Prepare method overrides.
        try {
            mbdToUse.prepareMethodOverrides();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                    beanName, "Validation of method overrides failed", ex);
        }

        try {
            // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            if (bean != null) {
                return bean;
            }
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                    "BeanPostProcessor before instantiation of bean failed", ex);
        }

        try {
            //这里去创建bean对象
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            if (logger.isDebugEnabled()) {
                logger.debug("Finished creating instance of bean '" + beanName + "'");
            }
            return beanInstance;
        }
        catch (BeanCreationException ex) {
            // A previously detected exception with proper bean creation context already...
            throw ex;
        }
        catch (ImplicitlyAppearedSingletonException ex) {
            // An IllegalStateException to be communicated up to DefaultSingletonBeanRegistry...
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
        }
    }
    
    //这里去创建bean对象
    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
            throws BeanCreationException {

        // Instantiate the bean.
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            //反射创建bean对象,调用无参数构告函数,记住这里它是非完整对象。
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        final Object bean = instanceWrapper.getWrappedInstance();
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        // Allow post-processors to modify the merged bean definition.
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "Post-processing of merged bean definition failed", ex);
                }
                mbd.postProcessed = true;
            }
        }

        /*
        这里判断是单例,且是循环依赖,且是标记中已有,标中已有指开始创建了。
        */
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            //为true就走这里
            if (logger.isDebugEnabled()) {
                logger.debug("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");
            }
            
            //把非完整对象放入三级缓存
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            //在这里给非完整对象属性进行赋值,如果属性也是Spring容器对象,它也会走doGetBean()获取对象给属性赋值。
            populateBean(beanName, mbd, instanceWrapper);
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        catch (Throwable ex) {
            if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
                throw (BeanCreationException) ex;
            }
            else {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
            }
        }

        if (earlySingletonExposure) {
            Object earlySingletonReference = getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                }
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                    for (String dependentBean : dependentBeans) {
                        if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }
                    if (!actualDependentBeans.isEmpty()) {
                        throw new BeanCurrentlyInCreationException(beanName,
                                "Bean with name '" + beanName + "' has been injected into other beans [" +
                                StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                                "] in its raw version as part of a circular reference, but has eventually been " +
                                "wrapped. This means that said other beans do not use the final version of the " +
                                "bean. This is often the result of over-eager type matching - consider using " +
                                "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }

        // Register bean as disposable.
        try {
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
        }

        return exposedObject;
    }
    
    //把非完整对象放入三级缓存
    protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(singletonFactory, "Singleton factory must not be null");
        synchronized (this.singletonObjects) {
            //如果一级缓存没有该对象,就把该对象放入三级缓存
            if (!this.singletonObjects.containsKey(beanName)) {
                //放入三级缓存(非完整对象)
                this.singletonFactories.put(beanName, singletonFactory);
                //从二级缓存移出
                this.earlySingletonObjects.remove(beanName);
                //记录beanname,可以理解为Spring的创建对象的日志记录
                this.registeredSingletons.add(beanName);
            }
        }
    }

看上面代码时,要有这个逻辑,首先创建自己时是在三级缓存(非完整对象),创建好了自己再去给属性赋值,属性被同样的方法递归创建,创建时发现依赖的对象(属性)在三级缓存就把其移到二级缓存,如果没有继续递归创建,直到属性赋值完(完整对象),再把自己移到一级缓存,二级和三级存储的是非完整对象,一级存储的是完整对象,其实这里我认为设计最巧妙的是二级缓存,我无法用文字表述,自己悟吧!二级缓存是防第三者利器,如果只有两级缓存,将防不到第三者。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值