当前位置: 首页>后端>正文

Spring的生命周期

Spring IOC

IOC(Inversion of Control),即控制反转,IOC意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制;即由容器来帮忙创建注入依赖对象
DI(Dependency Injection),即依赖注入,控制反转是通过依赖注入实现的,IOC是设计思想,DI是实现方式。

  • BeanFactory
  • ApplicationContext
    • GenericApplicationContext
      是初始化的时候就创建容器,往后的每次refresh都不会更改
    • AbstractRefreshableApplicationContext
      AbstractRefreshableApplicationContext及子类的每次refresh都是先清除已有(如果不存在就创建)的容器,然后再重新创建;AbstractRefreshableApplicationContext及子类无法做到GenericApplicationContext混合搭配从不同源头获取bean的定义信息
    • FileSystemXmlApplicationContext
      从文件系统下加载上下文定义,适用于xml配置的方式
    • ClassPathXmlApplicationContext
      从类路径下加载上下文定义,适用于xml配置的方式
    • AnnotationConfigApplicationContext
      基于java的配置类中加载上下文定义,适用java注解的方式
    • ConfigurableApplicationContext
      扩展于 ApplicationContext,它新增加了两个主要的方法: refresh()和 close(),让 ApplicationContext 具有启动、刷新和关闭应用上下文的能力
  • BeanDefinition
    定义了各种Bean对象及其相互的关系

IOC初始化

IoC初始化的流程,是把最终的将Bean的定义即BeanDefinition放到beanDefinitionMap中

Spring AOP

AOP(Aspect Oriented Programming),即面向切面编程。

Spring AOP 就是基于动态代理的,如果要代理的对象,实现了某个接口,那么Spring AOP会使用JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候Spring AOP会使用Cglib ,这时候Spring AOP会使用 Cglib 生成一个被代理对象的子类来作为代理

Spring Bean生命周期

  • 实例化(Instantiation)
  • 属性赋值(Populate)
  • 初始化(Initialization)
    // 分别调用Bean实现的XXXAware接口的接口方法、Bean实现InitializingBean接口的afterPropertiesSet方法、Bean实现的init_method方法
  • 销毁(Destruction)
    调用DisposableBean接口的destory方法
Spring的生命周期,第1张

getBean->doGetBean->createBean->doCreateBean
doCreateBean方法分别调用下面三个方法:
->createBeanInstance
->populateBean
->initializeBean

refresh->finishBeanFactoryInitialization->getBean

    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

        // Instantiate the bean.
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        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;
            }
        }

        // Eagerly cache singletons to be able to resolve circular references
        // even when triggered by lifecycle interfaces like BeanFactoryAware.
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            if (logger.isTraceEnabled()) {
                logger.trace("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 {
            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 " +
                                "'getBeanNamesForType' 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 Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                // 调用Aware方法
                invokeAwareMethods(beanName, bean);
                return null;
            }, getAccessControlContext());
        }
        else {
            // 调用Aware方法
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
           //遍历调用BeanPostProcessor的BeanPostProcessor方法
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            // 分别调用InitializingBean的afterPropertiesSet方法、init_method方法
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }
        if (mbd == null || !mbd.isSynthetic()) {
            //遍历调用BeanPostProcessor的BeanPostProcessor方法
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }
Spring的生命周期,第2张

InstantiationAwareBeanPostProcessor继承了BeanPostProcessor接口,InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation方法在doCreateBean之前调用,也就是在bean实例化之前调用的,这也是Aop等功能实现的关键点。
InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation方法在populateBean方法里面开始属性填充之前调用。

SpringMVC

Spring的生命周期,第3张

Spring设计模式

  • 工厂方法
    FactoryBean接口
  • 工厂模式
    Spring使用工厂模式通过 BeanFactory、ApplicationContext 创建 bean 对象
  • 代理模式
    Spring AOP 功能的实现
  • 单例模式
    Spring 中的 Bean 默认都是单例的
  • 模板方法模式
    Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式
  • 装饰器模式
    Spring 中用到的包装器模式在类名上含有 Wrapper或者 Decorator。这些类基本上都是动态地给一个对象添加一些额外的职责
  • 适配器模式
    SpringMVC中的适配器HandlerAdatper
  • 观察者模式
    Spring 事件驱动模型
// 定义一个事件,继承自ApplicationEvent并且写相应的构造函数
public class DemoEvent extends ApplicationEvent{
    private static final long serialVersionUID = 1L;

    private String message;

    public DemoEvent(Object source,String message){
        super(source);
        this.message = message;
    }

    public String getMessage() {
         return message;
          }

    
// 定义一个事件监听者,实现ApplicationListener接口,重写 onApplicationEvent() 方法;
@Component
public class DemoListener implements ApplicationListener<DemoEvent>{

    //使用onApplicationEvent接收消息
    @Override
    public void onApplicationEvent(DemoEvent event) {
        String msg = event.getMessage();
        System.out.println("接收到的信息是:"+msg);
    }

}
// 发布事件,可以通过ApplicationEventPublisher  的 publishEvent() 方法发布消息。
@Component
public class DemoPublisher {

    @Autowired
    ApplicationContext applicationContext;

    public void publish(String message){
        //发布事件
        applicationContext.publishEvent(new DemoEvent(this, message));
    }
}

Spring事务失效

事务传播机制:

  • REQUIRED
    如果当前上下文中存在事务,那么加入该事务,如果不存在事务,创建一个事务,这是默认的传播属性值。
  • SUPPORTS
    如果当前上下文存在事务,则支持事务加入事务,如果不存在事务,则使用非事务的方式执行。
  • MANDATORY
    如果当前存在一个事务,则加入该事务;否则,抛出异常
  • REQUIRES_NEW
    创建一个新的事务,并且如果存在一个事务,则将该事务挂起
  • NOT_SUPPORTED
    以非事务方式执行操作,如果当前存在一个事务,则将该事务挂起
  • NEVER
    以非事务方式执行操作,如果当前存在一个事务,则抛出异常
  • NESTED
    如果当前存在一个事务,则在嵌套事务内执行。如果没有事务,则按 REQUIRED传播级别执行。嵌套事务是外部事务的一部分,可以在外部事务提交或回滚时部分提交或回滚

@Transational事务失效场景:

  • 方法不是public方法

  • 方法用final、static修饰
    如果一个方法被声明为 final或者 static,则该方法不能被子类重写,也就是说无法在该方法上进行动态代理,这会导致 Spring无法生成事务代理对象来管理事务

  • 同一个类中,方法内部调用
    解决方法:被调用方法拆到新的Service类、注入自己、AopContext.currentProxy()获取代理对象

  • 事务注解被覆盖导致事务失效

  • 多线程调用
    不同线程获取的数据库连接不一样,从而是两个不同的事务

  • 异常被捕获并处理了,没有重新抛出

  • 手动抛了别的异常
    因为Spring默认只处理 RuntimeException和Error,对于普通的 Exception不会回滚,除非,用 rollbackFor属性指定配置。
    解决方案:添加属性配置 @Transactional(rollbackFor = Exception.class)

@Autowire、@Resource区别

  • 出处不一样
    @Autowire 是Spring定义注解,与Spring强耦合,其它框架用不了。
    @Resoure是JSR-250提供的Java标准,绝大部分框架都支持。
  • 注解应用地方不一样
    @Autowired能够用在:构造器、方法、参数、成员变量和注解上。
    @Resource能用在:类、成员变量和方法上。
  • 装配方式不一样
    @Autowire默认按byType自动装配,如果要使用byName,需要使用@Qualifier一起配合。
    而@Resource默认byName自动装配,如果指定了name,则用byName自动装配,如果指定了type,则用byType自动装配,如果同时指定name和type,查找唯一匹配的bean。

https://www.xamrdz.com/backend/3uk1932919.html

相关文章: