精华内容
下载资源
问答
  • 2021-03-21 10:47:41

    netbeans/updates/6.1/uc/final/stable/cata log_zh_CN.xml.gz 然后 UML 插件就可以找到了 把上面网址添加到 然后可以搜到插件 UML 点安装 然后新建项目 ......

    Netbeans创建web项目_IT/计算机_专业资料。Netbeans创建web项目图形学习教程。 Web 应用程序开发简介本文档将向您介绍有关使用 NetBeans IDE 开发 Web 应用程序的......

    5. 调试项目 在 Test.java 文件中,将光标放置在 System.out.println("Welcome to " + netbeans);这一行,后按 Ctrl-F8 设置断点。 或者直接在该行前的边框......

    NetBeans 的下载与安装。 2. 在 NetBeans 下新建工程。 3. 在 NetBeans 下编写 Java 源程序。 4. 在 NetBeans 下编译 Java 源程序。 5. 在 NetBeans ......

    NETBEANS JAVA GUI 开发背景设置攻略开发环境:Netbeans 7.0.1 建立项目:java 应用程序 步骤: 1. 建立 Frame 窗体: 2. 开始建立层次结构控件: 3. 在 ......

    NetBeans 6.0 为 Java 提供的新功能和扩展功能 NetBeans 6.0 提供了众多新功能和扩展功能,众所周知的 GUI 设计器(Matisse 项目)也从 5.5 版本开始得到了极大......

    最后完成的登录窗口如下图所示: 1、创建登录窗体类 、创建登录窗体类首先启动 NetBeans IDE,右键单击项目,在弹出的上下文菜单中,依次选择【新建】|【JFrame 窗体......

    NetBeans 无法使用编码 GBK 安全地打开该文件以及 java 工程出现乱码的解决方法今天用 NetBeans 打开包含路径里面的 UTF-8 编码的文件时,提示:NetBeans 无法 使用......

    则netbeans自动为数据成员生成get/set方法 public static void main(String[] args) { package com.jsp; System.out.println("test JavaBean!"); public class......

    NetBeans;API 平台;富客户端应用程序 Java 摘要:开放源码的 NetBeans IDE 构建于 NetBeans 平台并提供 NetBeans API 供其它模块调用.NetBeans 的模块化设计使得......

    补: 建议你到 http://netbeans.org/downloads/index.html 直接下 NetBeans6.9 (语言: 简体中文 NetBeans IDE 下载包 all) 的吧。 执行中出现 java.lang.......

    六 检查运行环境 1.再次启动 NetBeans IDE,先检查是否可以编写和运行 java 应用程序 点击“文件”――“新建项目” ,如下图操作 显示如下窗口: 选择“常规”―......

    Netbeans过滤器编程 1.什么是过滤器?过滤器的生命周期与web容器相同 ...

    Tab * 变量重命名:Ctrl-R * Javadoc 弹出框提示:Ctrl-ShiftSpace 这里所列出的 NetBeans 快捷键是从 NetBeans 一份文档中直接 copy 出来,放 在这里方便查阅......

    标签: maven| netbeans| maven netbeans实用安装开发配置指南_计算机软件及应用_IT/计算机_专业资料。java maven项目软件管理,软件构建指南。简单又实用。 ...

    如果看不清出里面的图,请放大到 150% 使用 NetBeans 设计 GUI 1. 文件-新建项目-选择 Java 应用程序 2. 输入项目名称,不要选择“创建主类” 3.新建包 4.......

    用NetBeans写的Java计算器_计算机软件及应用_IT/计算机_专业资料。...

    福建农林大学实验报告实验一一、实验目的: 1、熟悉 JAVA 开发环境(NetBeans/JDK) 2、认识 Java 程序结构。 Java 开发环境 二、实验内容: 1、配置 JDK,编译调试......

    Java程序设计——基于JDK6和NetBeans实现习题解答与实验指导_计算机软件及应用_IT/计算机_专业资料。 +申请认证 文档贡献者 炎帝 铁路工程师 11479 49236 0.0 ......

    ("java:comp/env/sample"); DataSource dataSource=(DataSource)context.lookup(“sample”); //netbeans6.9下直接用 Connection conn=null; //数据库连接对象 ......

    更多相关内容
  • 周期处理器(CPU),支持以下指令:lw、sw、beq、addi、add、sub、and、or、slt。使用的开发环境是vivado,文件在压缩包中的single_cycle_processor.xpr内。压缩包内有单周期CPU的示意图。
  • sar数据圆周期滤波matlab程序,导入需要滤波的数据,一键实现圆周期和均值等滤波。滤波效果还可以,可以见到明显的去噪。
  • 周期CPU设计vivado

    2018-12-03 17:10:27
    周期CPU设计的文件,语言verilog,打开之后,可以用vivado直接跑,思路是正确的,具体的指令需要根据要求做小幅度调整
  • 周期MIPS CPU数据通路设计,这个是华中科技大学谭志虎老师所讲的那个设计,内含有circ数据通路和实验报告,这个实验报告我写了一万多字,足够足够详细,保证你答辩的时候非常顺畅,直接导入Logisim就可以运行。
  • 周期CPU Vivado

    2018-07-25 12:24:10
    用Vivado实现一个单周期CPU,不包含烧电路板内容,根据2018年的计算机组成原理及接口技术的实验课程要求。
  • Verilog单周期CPU配套源码,两个压缩包一个是完整的工程,一个是可以直接导入的函数库,任选一个即可。关于本代码的详细解释请移步于本人博客:https://blog.csdn.net/Accelerato/article/details/86546751
  • 联谊移动台周期步进程序。程序中糅合了快门程序。需要先导入移动台和快门子vi。
  • 该支持包中的驾驶循环可以导入到“车辆动力学”块集的“驾驶循环源”模块中,从而使您可以轻松访问世界各地(包括US06,HWFET,NEDC,日语10)常用的超过50个驾驶循环。 -15模式,还有许多其他模式。 某些传动周期...
  • 完整的Android片段和活动生命周期 在努力弄清楚各个部分如何组合之后,我进行了一些研究,并整理了完整的Android Activity / Fragment... 然后将其导出到SVG,进行手工调整以固定字体大小,然后导入到以进行SVG,PDF
  • 一文读懂 Spring Bean 的生命周期

    万次阅读 多人点赞 2021-07-05 23:02:56
    今天我们来说一说 Spring Bean 的生命周期,小伙伴们应该在面试中经常遇到,这是正常现象。因为 Spring Bean 的生命周期是除了 IoC、AOP 几个核心概念之外最重要概念,大家务必拿下。可 Spring 源代码又比较复杂,...

    欢迎大家关注我的微信公众号【老周聊架构】,Java后端主流技术栈的原理、源码分析、架构以及各种互联网高并发、高性能、高可用的解决方案。

    一、前言

    今天我们来说一说 Spring Bean 的生命周期,小伙伴们应该在面试中经常遇到,这是正常现象。因为 Spring Bean 的生命周期是除了 IoC、AOP 几个核心概念之外最重要概念,大家务必拿下。可 Spring 源代码又比较复杂,跟着跟着就不知道跟到哪里去了,不太好拿下呀。这倒是真的,而且网上一上来就各种贴流程源码,对初学者来说是真的一脸懵逼,就像字都看的懂,但连在一块就不知道意思了,太绕了。

    本文老周试着讲的通俗易懂些,让更多的小伙伴们轻松的读懂 Spring Bean 的生命周期,并有对它有继续研究学习的想法,那我写此文的目的也就达到了。

    我们讲 Spring Bean 的生命周期之前先来了解两个概念:

    1.1 什么是 Bean

    我们来看下 Spring Framework 的官方文档:

    In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and otherwise managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your application. Beans, and the dependencies among them, are reflected in the configuration metadata used by a container.

    简而言之,bean 是由 Spring IoC 容器实例化、组装和管理的对象。

    1.2 什么是 Spring Bean 的生命周期

    对于普通的 Java 对象,当 new 的时候创建对象,然后该对象就能够使用了。一旦该对象不再被使用,则由 Java 自动进行垃圾回收。

    而 Spring 中的对象是 bean,bean 和普通的 Java 对象没啥大的区别,只不过 Spring 不再自己去 new 对象了,而是由 IoC 容器去帮助我们实例化对象并且管理它,我们需要哪个对象,去问 IoC 容器要即可。IoC 其实就是解决对象之间的耦合问题,Spring Bean 的生命周期完全由容器控制。

    二、Spring Bean 的生命周期

    这里老周必须要提一下,这里我们说的 Spring Bean 的生命周期主要指的是 singleton bean,对于 prototype 的 bean ,Spring 在创建好交给使用者之后则不会再管理后续的生命周期。

    我们也来复习下 Spring 中的 bean 的作用域有哪些?

    • singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的。
    • prototype : 每次请求都会创建一个新的 bean 实例。
    • request : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP request 内有效。
    • session : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP session 内有效。
    • global-session: 全局 session 作用域,仅仅在基于 Portlet 的 web 应用中才有意义,Spring5 已经没有了。Portlet 是能够生成语义代码(例如:HTML)片段的小型 Java Web 插件。它们基于 portlet 容器,可以像 servlet 一样处理 HTTP 请求。但是,与 servlet 不同,每个 portlet 都有不同的会话。

    我们知道对于普通的 Java 对象来说,它们的生命周期就是:

    • 实例化
    • 该对象不再被使用时通过垃圾回收机制进行回收

    而对于 Spring Bean 的生命周期来说:

    • 实例化 Instantiation
    • 属性赋值 Populate
    • 初始化 Initialization
    • 销毁 Destruction

    实例化 -> 属性赋值 -> 初始化 -> 销毁

    只有四个步骤,这样拆解的话是不是感觉也不难?不像其他人写的那样直接一上来就各种 BeanPostProcessor、BeanFactoryPostProcessor 全部怼进流程里去,别说读者看着头大,自己写的可能短时间内还记得流程,隔个一段时间,你可能都不知道自己写了个啥。

    本来老周想通过 Bean 创建流程入口
    AbstractApplicationContext#refresh() 方法的 finishBeanFactoryInitialization(beanFactory) 处带大家跟一下源码,想了想还是不带入过多的代码进来,直接给到最终的主要逻辑。

    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
        }
    
        if (instanceWrapper == null) {
        	// 实例化阶段
            instanceWrapper = this.createBeanInstance(beanName, mbd, args);
        }
    
        ...
    
        Object exposedObject = bean;
    
        try {
        	// 属性赋值阶段
            this.populateBean(beanName, mbd, instanceWrapper);
            // 初始化阶段
            exposedObject = this.initializeBean(beanName, exposedObject, mbd);
        } catch (Throwable var18) {
            ...
        }
    
        ...
    }
    

    至于销毁,是在容器关闭时调用的,详见 ConfigurableApplicationContext#close()

    是不是很清爽了?至于 BeanPostProcessor、BeanFactoryPostProcessor 以及其他的类,在老周看来,只不过是对主流程四个步骤的一系列扩展点而已。

    三、Spring Bean 的生命周期的扩展点

    Spring Bean 的生命周期的扩展点超级多,老周这里不可能全部列出来,只说核心的扩展点。这也就是为什么 Spring 的扩展性很好的原因,开了很多的口子,尽可能让某个功能高内聚松耦合,用户需要哪个功能就用哪个,而不是直接来一个大而全的东西。

    3.1 Bean 自身的方法

    比如构造函数、getter/setter 以及 init-method 和 destory-method 所指定的方法等,也就对应着上文说的实例化 -> 属性赋值 -> 初始化 -> 销毁四个阶段。

    在这里插入图片描述
    3.2 容器级的方法(BeanPostProcessor 一系列接口)

    主要是后处理器方法,比如下图的 InstantiationAwareBeanPostProcessorBeanPostProcessor 接口方法。这些接口的实现类是独立于 Bean 的,并且会注册到 Spring 容器中。在 Spring 容器创建任何 Bean 的时候,这些后处理器都会发生作用。

    在这里插入图片描述
    3.2.1 InstantiationAwareBeanPostProcessor 源码分析

    我们翻一下源码发现 InstantiationAwareBeanPostProcessor 是继承了 BeanPostProcessor

    在这里插入图片描述
    在这里插入图片描述

    • InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 调用点

    Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
    返回值:如果返回的不为null,那么后续的Bean的创建流程【实例化、初始化afterProperties】都不会执行,而是直接使用返回的快捷Bean,此时的正常执行顺序如下:
    InstantiationAwareBeanPostProcessor接口中的postProcessBeforeInstantiation,在实例化之前调用。
    BeanPostProcessor接口中的postProcessAfterInitialization,在实例化之后调用。

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    总之,postProcessBeforeInstantiation 在 doCreateBean 之前调用,也就是在 bean 实例化之前调用的,英文源码注释解释道该方法的返回值会替换原本的 Bean 作为代理,这也是 AOP 等功能实现的关键点。

    • InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation 调用点

    boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException
    正常情况下在实例化之后在执行populateBean之前调用
    返回值:如果有指定的bean的时候返回false,那么后续的属性填充和属性依赖注入【populateBean】将不会执行,同时后续的postProcessPropertyValues将不会执行,但是初始化和BeanPostProcessor的仍然会执行。

    在这里插入图片描述

    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
    实例化之后调用,在方法applyPropertyValues【属性填充】之前
    返回值:如果返回null,那么将不会进行后续的属性填充,比如依赖注入等,如果返回的pvs额外的添加了属性,那么后续会填充到该类对应的属性中。
    pvs:PropertyValues对象,用于封装指定类的对象,简单来说就是PropertyValue的集合,里面相当于以key-value形式存放类的属性和值。
    pds:PropertyDescriptor对象数组,PropertyDescriptor相当于存储类的属性,不过可以调用set,get方法设置和获取对应属性的值。

    在这里插入图片描述
    3.2.2 BeanPostProcessor 源码分析

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

    在这里插入图片描述
    进入初始化接口:

    在这里插入图片描述
    我们先来看

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization

    在这里插入图片描述

    • 首先获取到所有的后置处理器 getBeanPostProcessors()
    • 在 for 循环中依次调用后置处理器的方法 processor.postProcessBeforeInitialization(result, beanName);
    • 进入 postProcessBeforeInitialization 方法

    org.springframework.context.support.ApplicationContextAwareProcessor#postProcessBeforeInitialization

    在这里插入图片描述

    进入 invokeAwareInterfaces(bean); 方法,当前 bean 实现了 ApplicationContextAware 接口。

    在这里插入图片描述

    • ApplicationContextAwareProcessor#postProcessBeforeInitialization 首先判断此 bean 是不是各种的Aware,如果是它列举的那几个 Aware 就获取 Bean 工厂的权限,可以向容器中导入相关的上下文环境,目的是为了 Bean 实例能够获取到相关的上下文,如果不是它列举的几个 Aware,那就调用 invokeAwareInterfaces(bean),向容器中添加相关接口的上下文环境。

    3.3 工厂后处理器方法(BeanFactoryProcessor 一系列接口)

    包括 AspectJWeavingEnablerCustomAutowireConfigurerConfigurationClassPostProcessor 等。这些都是 Spring 框架中已经实现好的 BeanFactoryPostProcessor,用来实现某些特定的功能。

    我们知道 Spring IoC 容器初始化的关键环节就在 org.springframework.context.support.AbstractApplicationContext#refresh 方法中 ,容器创建的主体流程都在这个方法里面,这个方法是真的重要!!!

    对于工厂后处理器方法老周这里直接带你看 invokeBeanFactoryPostProcessors(beanFactory); 方法,这个方法处理的是 BeanFactoryPostProcessor 接口的 Bean。调用方法如下:

    在这里插入图片描述
    跟到最重要的方法里去,代码虽长,但逻辑中规中矩。

    BeanFactoryPostProcessor:一切处理 BeanFactory 的父接口
    BeanDefinitionRegistryPostProcessor:实现了 BeanFactoryPostProcessor 接口的接口

    在这里插入图片描述
    流程说明:

    • 调用 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry(registry) 方法。参数 beanFactoryPostProcessors 传入的优先处理掉。然后获取容器注册的,对于这些 Bean 按照 PriorityOrdered 接口、Ordered、没有排序接口的实例分别进行处理。
    • 调用 BeanFactoryPostProcessor#postProcessBeanFactory(beanFactory) 方法。备注:BeanDefinitionRegistryPostProcessor 属于 BeanFactoryPostProcessor 子接口。先处理属于 BeanDefinitionRegistryPostProcessor 接口实例的 postProcessBeanFactory(beanFactory) 方法,然后获取容器注册的。对于这些 Bean 按照 PriorityOrdered 接口、Ordered、没有排序接口的实例分别进行处理。

    3.4 Bean 级生命周期方法

    可以理解为 Bean 类直接实现接口的方法,比如 BeanNameAwareBeanFactoryAwareApplicationContextAwareInitializingBeanDisposableBean 等方法,这些方法只对当前 Bean 生效。

    3.4.1 Aware 类型的接口

    Aware 类型的接口的作用就是让我们能够拿到 Spring 容器中的一些资源。基本都能够见名知意,Aware 之前的名字就是可以拿到什么资源,例如 BeanNameAware 可以拿到 BeanName,以此类推。调用时机需要注意:所有的 Aware 方法都是在初始化阶段之前调用的

    Aware 接口众多,这里同样通过分类的方式帮助大家记忆。Aware 接口具体可以分为两组,至于为什么这么分,详见下面的源码分析。如下排列顺序同样也是 Aware 接口的执行顺序,能够见名知意的接口不再解释。

    Aware Group1

    • BeanNameAware
    • BeanClassLoaderAware
    • BeanFactoryAware

    Aware Group2

    • EnvironmentAware
    • EmbeddedValueResolverAware
      这个知道的人可能不多,实现该接口能够获取 Spring EL 解析器,用户的自定义注解需要支持 SPEL 表达式的时候可以使用,非常方便。
    • ApplicationContextAware(ResourceLoaderAware/ApplicationEventPublisherAware/MessageSourceAware)
      这几个接口可能让人有点懵,实际上这几个接口可以一起记,其返回值实质上都是当前的 ApplicationContext 对象,因为 ApplicationContext 是一个复合接口,如下:
      在这里插入图片描述

    Aware 调用时机源码分析

    在这里插入图片描述
    可以看到并不是所有的 Aware 接口都使用同样的方式调用。Bean××Aware 都是在代码中直接调用的,而 ApplicationContext 相关的 Aware 都是通过 BeanPostProcessor#postProcessBeforeInitialization() 实现的。感兴趣的可以自己看一下 ApplicationContextAwareProcessor 这个类的源码,就是判断当前创建的 Bean 是否实现了相关的 Aware 方法,如果实现了会调用回调方法将资源传递给 Bean。

    BeanPostProcessor 的调用时机也能在这里体现,包围住 invokeInitMethods 方法,也就说明了在初始化阶段的前后执行。

    关于 Aware 接口的执行顺序,其实只需要记住第一组在第二组执行之前就行了。

    3.4.2 生命周期接口

    至于剩下的两个生命周期接口就很简单了,实例化和属性赋值都是 Spring 帮助我们做的,能够自己实现的有初始化和销毁两个生命周期阶段。

    • InitializingBean 对应生命周期的初始化阶段,在上面源码的 invokeInitMethods(beanName, wrappedBean, mbd);方法中调用。
      有一点需要注意,因为 Aware 方法都是执行在初始化方法之前,所以可以在初始化方法中放心大胆的使用 Aware 接口获取的资源,这也是我们自定义扩展 Spring 的常用方式。
      除了实现 InitializingBean 接口之外还能通过注解或者 xml 配置的方式指定初始化方法,至于这几种定义方式的调用顺序其实没有必要记。因为这几个方法对应的都是同一个生命周期,只是实现方式不同,我们一般只采用其中一种方式。
    • DisposableBean 类似于 InitializingBean,对应生命周期的销毁阶段,以ConfigurableApplicationContext#close()方法作为入口,实现是通过循环取所有实现了 DisposableBean 接口的 Bean 然后调用其 destroy() 方法,感兴趣的可以自行跟一下源码。

    3.5 Spring Bean 生命周期流程图

    在这里插入图片描述

    四、常用接口说明

    4.1 BeanNameAware

    该接口只有一个方法 setBeanName(String name),用来获取 bean 的 id 或者 name

    4.2 BeanFactoryAware

    该接口只有一个方法 setBeanFactory(BeanFactory beanFactory),用来获取当前环境中的 BeanFactory

    4.3 ApplicationContextAware

    该接口只有一个方法 setApplicationContext(ApplicationContext applicationContext),用来获取当前环境中的 ApplicationContext

    4.4 InitializingBean

    该接口只有一个方法 afterPropertiesSet(),在属性注入完成后调用

    4.5 DisposableBean

    该接口只有一个方法 destroy(),在容器销毁的时候调用,在用户指定的 destroy-method 之前调用

    4.6 BeanPostProcessor

    该接口有两个方法:

    • postProcessBeforeInitialization(Object bean, String beanName):在初始化之前调用此方法
    • postProcessAfterInitialization(Object bean, String beanName):在初始化之后调用此方法

    通过方法签名我们可以知道,我们可以通过 beanName 来筛选出我们需要进行个性化定制的 bean。

    4.7 InstantiationAwareBeanPostProcessor

    该类是 BeanPostProcessor 的子接口,常用的有如下三个方法:

    • postProcessBeforeInstantiation(Class beanClass, String beanName):在bean实例化之前调用
    • postProcessProperties(PropertyValues pvs, Object bean, String beanName):在bean实例化之后、设置属性前调用
    • postProcessAfterInstantiation(Class beanClass, String beanName):在bean实例化之后调用

    五、代码演示

    思路:创建一个类 UserBean ,让其实现几个特殊的接口,并分别在接口实现的构造器、接口方法中断点,观察线程调用栈,分析出 Bean 对象创建和管理关键点的触发时机。

    5.1 UserBean 类

    @Component
    public class UserBean implements InitializingBean, BeanNameAware, DisposableBean, ApplicationContextAware {
    	private int id;
    
    	private String name;
    
    	public UserBean(int id, String name) {
    		this.id = id;
    		this.name = name;
    		System.out.println("2. 调用构造函数");
    	}
    
    	public int getId() {
    		return id;
    	}
    
    	public void setId(int id) {
    		this.id = id;
    		System.out.println("5. 属性注入 id");
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    		System.out.println("5. 属性注入 name");
    	}
    
    	@Override
    	public void setBeanName(String name) {
    		System.out.println("6. 调用 BeanNameAware.setBeanName() 方法");
    	}
    
    	@Override
    	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    		UserBean userBean = (UserBean) applicationContext.getBean("userBean");
    		System.out.println(userBean);
    		System.out.println("7. 调用 BeanNameAware.setBeanName() 方法");
    	}
    
    	@Override
    	public void afterPropertiesSet() throws Exception {
    		System.out.println("9. 调用 InitializingBean.afterPropertiesSet() 方法");
    	}
    
    	public void myInit() {
    		System.out.println("10. 调用 init-method 方法");
    	}
    
    	@Override
    	public void destroy() throws Exception {
    		System.out.println("12. 调用 DisposableBean.destroy() 方法");
    	}
    
    	public void myDestroy() {
    		System.out.println("13. 调用 destroy-method 方法");
    	}
    
    	@Override
    	public String toString() {
    		return "UserBean{" +
    				"id=" + id +
    				", name='" + name + '\'' +
    				'}';
    	}
    }
    

    5.2 InstantiationAwareBeanPostProcessor 接口实现类

    @Component
    public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    	@Override
    	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    		if ("userBean".equals(beanName)) {
    			System.out.println("1. 调用 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() 方法");
    		}
    		return null;
    	}
    
    	@Override
    	public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
    		if ("userBean".equals(beanName)) {
    			UserBean userBean = (UserBean) bean;
    			System.out.println("3. 调用 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 方法");
    			System.out.println(userBean);
    		}
    		return true;
    	}
    
    	@Override
    	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
    		if ("userBean".equals(beanName)) {
    			System.out.println("4. 调用 InstantiationAwareBeanPostProcessor.postProcessProperties() 方法");
    		}
    		return null;
    	}
    }
    

    5.3 BeanPostProcessor 接口实现类

    @Component
    public class MyBeanPostProcessor implements BeanPostProcessor {
    	@Override
    	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    		if ("userBean".equals(beanName)) {
    			System.out.println("8. 调用 BeanPostProcessor.postProcessBeforeInitialization() 方法");
    		}
    		return bean;
    	}
    
    	@Override
    	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    		if ("userBean".equals(beanName)) {
    			System.out.println("11. 调用 BeanPostProcessor.postProcessAfterInitialization() 方法");
    		}
    		return bean;
    	}
    }
    

    5.4 BeanFactoryPostProcessor 接口实现类

    @Component
    public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    	@Override
    	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    		System.out.println("0. 调用 BeanFactoryPostProcessor.postProcessBeanFactory() 方法");
    	}
    }
    

    5.5 applicationContext.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	   xsi:schemaLocation="
    	    http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd
    ">
    
    	<bean class="com.riemann.test.MyInstantiationAwareBeanPostProcessor" />
    
    	<bean id="userBean" class="com.riemann.test.UserBean" init-method="myInit" destroy-method="myDestroy">
    		<!-- 构造函数注入 -->
    		<constructor-arg index="0" type="int">
    			<value>1</value>
    		</constructor-arg>
    		<constructor-arg index="1" type="java.lang.String">
    			<value>微信公众号【老周聊架构】</value>
    		</constructor-arg>
    
    		<!-- setter方法注入 -->
    		<property name="id" value="2"/>
    		<property name="name" value="riemann"/>
    	</bean>
    
    	<bean class="com.riemann.test.MyBeanPostProcessor" />
    
    	<bean class="com.riemann.test.MyBeanFactoryPostProcessor" />
    	
    </beans>
    

    5.6 测试类

    public class BeanLifeCycleTest {
    	public static void main(String[] args) {
    		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    		UserBean user = (UserBean) applicationContext.getBean("userBean");
    		((AbstractApplicationContext) applicationContext).close();
    	}
    }
    

    5.7 控制台结果打印

    在这里插入图片描述

    展开全文
  • 导入包 对于 Python 3.X 系列, >>> from elements import elements >>> import elements.elements as elements 对于 Python2.X 系列, >>> import elements 基本用法 >>> elements.H >>> elements.hydrogen....
  • 项目风险管理思维:项目全寿命周期维度与公司组织架构维度,项目风险管理规划:风险政策制定与管理规划,项目风险识别与分析:关键(预研阶段)与重点(生产导入),项目风险应对与监督:项目风险应对、项目信息管理系统,...
  • Vue 3 生命周期完整指南

    万次阅读 2021-03-31 08:28:34
    例如,假设我们想访问mounted()和updated()生命周期钩子,可以这么写: // 选项 API 在组合API中使用Vue 3生命周期钩子 在组合API中,我们需要将生命周期钩子导入到项目中,才能使用,这有助于保持项目的轻量性。...

    highlight: a11y-dark
    theme: condensed-night-purple

    作者:Michael Thiessen
    译者:前端小智
    来源:news

    点赞再看,微信搜索**【大迁世界,B站关注前端小智】**这个没有大厂背景,但有着一股向上积极心态人。本文 GitHub https://github.com/qq449245884/xiaozhi 上已经收录,文章的已分类,也整理了很多我的文档,和教程资料。

    最近开源了一个 Vue 组件,还不够完善,欢迎大家来一起完善它,也希望大家能给个 star 支持一下,谢谢各位了。

    github 地址:https://github.com/qq449245884/vue-okr-tree

    Vue2 和 Vue3 中的生命周期钩子的工作方式非常相似,我们仍然可以访问相同的钩子,也希望将它们能用于相同的场景。

    如果项目使用 选项 API,就不必更改任何代码了,因为 Vue3 兼容以前的版本。

    当然,我们用 Vue3 就是要用它的 组合 API组合 API中访问这些钩子的方式略有不同,组合API在较大的Vue项目中特别有用。

    本文主要内容:

    1. Vue生命周期钩子有哪些
    2. 选项API中使用 Vue 生命周期钩子
    3. 组合API中使用Vue 3生命周期钩子
    4. 将 Vue2 的生命周期钩子代码更新到 Vue3
    5. 看看Vue 2和Vue 3中的每个生命周期钩子
    6. 创建
    7. 挂载
    8. 更新
    9. 卸载
    10. 激活
    11. Vue 3中的新调试钩子

    Vue生命周期钩子有哪些

    首先,来看一下 选项API 和 组合 API中 Vue 3生命周期钩子的图表。在深入细节之前,这能加深我们的理解。

    image.png

    本质上,每个主要Vue生命周期事件被分成两个钩子,分别在事件之前和之后调用。Vue应用程序中有4个主要事件(8个主要钩子)。

    • 创建 — 在组件创建时执行
    • 挂载 — DOM 被挂载时执行
    • 更新 — 当响应数据被修改时执行
    • 销毁 — 在元素被销毁之前立即运行

    选项API中使用 Vue 生命周期钩子

    使用 选项API,生命周期钩子是被暴露 Vue实例上的选项。我们不需要导入任何东西,只需要调用这个方法并为这个生命周期钩子编写代码。

    例如,假设我们想访问mounted()updated()生命周期钩子,可以这么写:

    // 选项 API
    <script>     
       export default {         
          mounted() {             
             console.log('mounted!')         
          },         
          updated() {             
             console.log('updated!')         
          }     
       }
    </script> 
    

    组合API中使用Vue 3生命周期钩子

    在组合API中,我们需要将生命周期钩子导入到项目中,才能使用,这有助于保持项目的轻量性。

    // 组合 API
    import { onMounted } from 'vue'
    

    除了beforecatecreated(它们被setup方法本身所取代),我们可以在setup方法中访问的API生命周期钩子有9个选项:

    • onBeforeMount – 在挂载开始之前被调用:相关的 render 函数首次被调用。

    • onMounted – 组件挂载时调用

    • onBeforeUpdate – 数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。

    • onUpdated – 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。

    • onBeforeUnmount – 在卸载组件实例之前调用。在这个阶段,实例仍然是完全正常的。

    • onUnmounted – 卸载组件实例后调用。调用此钩子时,组件实例的所有指令都被解除绑定,所有事件侦听器都被移除,所有子组件实例被卸载。

    • onActivated – 被 keep-alive 缓存的组件激活时调用。

    • onDeactivated – 被 keep-alive 缓存的组件停用时调用。

    • onErrorCaptured – 当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。

    使用事例:

    // 组合 API
    <script>
    import { onMounted } from 'vue'
    
    export default {
       setup () {
         onMounted(() => {
           console.log('mounted in the composition api!')
         })
       }
    }
    </script>
    

    将 Vue2 的生命周期钩子代码更新到 Vue3

    这个从Vue2 到Vue3的生命周期映射是直接从Vue 3 Composition API文档中获得的:

    • beforeCreate -> 使用 setup()

    • created -> 使用 setup()

    • beforeMount -> onBeforeMount

    • mounted -> onMounted

    • beforeUpdate -> onBeforeUpdate

    • updated -> onUpdated

    • beforeDestroy -> onBeforeUnmount

    • destroyed -> onUnmounted

    • errorCaptured -> onErrorCaptured

    深入了解每个生命周期钩子

    我们现在了解了两件重要的事情:

    • 我们可以使用的不同的生命周期钩子
    • 如何在选项API和组合API中使用它们

    我们深入一下每个生命周期钩子,看看它们是如何被使用的,我们可以在每个钩子中编写特定代码,来测试在Options API和Composition API中的各自的区别。

    beforeCreate() – 选项 API

    由于创建的挂钩是用于初始化所有响应数据和事件的事物,因此beforeCreate无法访问组件的任何响应数据和事件。

    以下面的代码块为例:

    // 选项 API
    export default {
       data() { 
         return { 
           val: 'hello'    
         }
       },
       beforeCreate() {     
         console.log('Value of val is: ' + this.val)   
       }
    }
    

    val的输出值是 undefined,因为尚未初始化数据,我们也不能在这调用组件方法。

    如果你想查看可用内容的完整列表,建议只运行console.log(this)来查看已初始化的内容。当使用选项API时,这做法在其他钩子中也很有用。

    created() – 选项 API

    如果我们要在组件创建时访问组件的数据和事件,可以把上面的 beforeCreatecreated代替。

    // 选项API
    export default {
       data() { 
         return { 
           val: 'hello'    
         }
       },
       created() {     
         console.log('Value of val is: ' + this.val)   
       }
    }
    

    其输出为Value of val is: hello,因为我们已经初始化了数据。

    在处理读/写反应数据时,使用created 的方法很有用。 例如,要进行API调用然后存储该值,则可以在此处进行此操作。

    最好在这里执行此操作,而不是在mounted 中执行此操作,因为它发生在Vue的同步初始化过程中,并且我们需要执行所有数据读取/写入操作。

    那么组合API的创建钩子呢?

    对于使用 组合API 的 Vue3 生命周期钩子,使用setup()方法替换beforecatecreated。这意味着,在这些方法中放入的任何代码现在都只在setup方法中。

    // 组合AP
    import { ref } from 'vue'
    
    export default {
       setup() {    
         const val = ref('hello') 
         console.log('Value of val is: ' + val.value)       
         return {         
           val
         }
       }
    }
    

    beforeMount() and onBeforeMount()

    在组件DOM实际渲染安装之前调用。在这一步中,根元素还不存在。在选项API中,可以使用this.$els来访问。在组合API中,为了做到这一点,必须在根元素上使用ref

    // 选项 API
    export default {
       beforeMount() {
         console.log(this.$el)
       }
     }
    

    组合API中使用 ref:

    // 组合 API
    <template>
       <div ref='root'>
         Hello World
       </div>
    </template> 
    
    import { ref, onBeforeMount } from 'vue'
    
    export default {
       setup() {
          const root = ref(null) 
          onBeforeMount(() => {   
             console.log(root.value) 
          }) 
          return { 
             root
          }
        },
        beforeMount() {
          console.log(this.$el)
        }
     }
    

    因为app.$el还没有创建,所以输出将是undefined

    mounted() and onMounted()

    在组件的第一次渲染后调用,该元素现在可用,允许直接DOM访问

    同样,在 选项API中,我们可以使用this.$el来访问我们的DOM,在组合API中,我们需要使用refs来访问Vue生命周期钩子中的DOM。

    import { ref, onMounted } from 'vue'
     
    
     export default {
       setup() {    /* 组合 API */
     
         const root = ref(null)
     
         onMounted(() => {
           console.log(root.value)
         })
     
    
         return {
           root
         }
       },
       mounted() { /* 选项 API */
         console.log(this.$el)
       }
     } 
    

    beforeUpdate() and onBeforeUpdate()

    数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。

    beforeUpdate对于跟踪对组件的编辑次数,甚至跟踪创建“撤消”功能的操作很有用。

    updated() and onUpdated()

    DOM更新后,updated的方法即会调用。

    <template>
        <div>
          <p>{{val}} | edited {{ count }} times</p>
          <button @click='val = Math.random(0, 100)'>Click to Change</button>
        </div>
     </template> 
    

    选项 API 方式:

     export default {
       data() {
          return {
            val: 0
          }
       },
       beforeUpdate() {
          console.log("beforeUpdate() val: " + this.val)
       },
       updated() {
          console.log("updated() val: " + this.val
       }
     } 
    

    组合API的方式:

    import { ref, onBeforeUpdate, onUpdated } from 'vue'
     
     export default {
       setup () {
         const count = ref(0)
         const val = ref(0)
     
         onBeforeUpdate(() => {
           count.value++;
           console.log("beforeUpdate");
         })
     
         onUpdated(() => {
           console.log("updated() val: " + val.value)
         })
     
         return {
           count, val
         }
       }
     }
    

    这些方法很有用,但是对于更多场景,我们需要使用的watch方法检测这些数据更改。 watch 之所以好用,是因为它给出了更改后的数据的旧值和新值。

    另一种选择是使用计算属性来基于元素更改状态。

    beforeUnmount() 和 onBeforeUnmounted()

    在卸载组件实例之前调用。在这个阶段,实例仍然是完全正常的。

    在 选项 API中,删除事件侦听器的示例如下所示。

    // 选项 API
    export default {
       mounted() {
         console.log('mount')
         window.addEventListener('resize', this.someMethod);
       },
       beforeUnmount() {
         console.log('unmount')
         window.removeEventListener('resize', this.someMethod);
       },
       methods: {
          someMethod() {
             // do smth
          }
       }
    } 
    
    // 组合API
    import { onMounted, onBeforeUnmount } from 'vue' 
    
     export default {
       setup () {
     
         const someMethod = () => {
           // do smth
         }
     
         onMounted(() => {
           console.log('mount')
           window.addEventListener('resize', someMethod);
         })
     
         onBeforeUnmount(() => {
           console.log('unmount')
           window.removeEventListener('resize', someMethod);
         })
     
       }
     }
    

    实际操作的一种方法是在Vite,vue-cli或任何支持热重载的开发环境中,更新代码时,某些组件将自行卸载并安装。

    unmounted() 和 onUnmounted()

    卸载组件实例后调用。调用此钩子时,组件实例的所有指令都被解除绑定,所有事件侦听器都被移除,所有子组件实例被卸载。

    import { onUnmounted } from 'vue'
    
    export default {
      setup () { /* 组合 API */
    
        onUnmounted(() => {
          console.log('unmounted')
        })
    
      },
      unmounted() { /* 选项 API */
        console.log('unmounted')
      }
    }
    

    activated() and onActivated()

    keep-alive 缓存的组件激活时调用。

    例如,如果我们使用keep-alive组件来管理不同的选项卡视图,每次在选项卡之间切换时,当前选项卡将运行这个 activated 钩子。

    假设我们使用keep-alive包装器进行以下动态组件。

    <template>
       <div>
         <span @click='tabName = "Tab1"'>Tab 1 </span>
         <span @click='tabName = "Tab2"'>Tab 2</span>
         <keep-alive>
           <component :is='tabName' class='tab-area'/>
         </keep-alive>
       </div>
    </template>
    
    <script>
    import Tab1 from './Tab1.vue'
    import Tab2 from './Tab2.vue'
    
    import { ref } from 'vue'
    
    export default {
      components: {
        Tab1,
        Tab2
      },
      setup () { /* 组合 API */
        const tabName = ref('Tab1')
    
        return {
          tabName
        }
      }
    }
    </script>
    

    Tab1.vue组件内部,我们可以像这样访问activated钩子。

    <template>
     <div>
     <h2>Tab 1</h2>
     <input type='text' placeholder='this content will persist!'/>
     </div>
    </template>
    
    <script>
    import { onActivated } from 'vue'
    
    export default {
     setup() {
        onActivated(() => {
           console.log('Tab 1 Activated')
        })
     }
    } 
    </script>
    

    deactivated() 和 onDeactivated()

    keep-alive 缓存的组件停用时调用。

    这个钩子在一些用例中很有用,比如当一个特定视图失去焦点时保存用户数据和触发动画。

    import { onActivated, onDeactivated } from 'vue'
    
    export default {
      setup() {
        onActivated(() => {
           console.log('Tab 1 Activated')
        })
    
        onDeactivated(() => {
           console.log('Tab 1 Deactivated')
        })
      }
    }
    
    

    现在,当我们在选项卡之间切换时,每个动态组件的状态都将被缓存和保存。

    4216299740-605e8878b7355_fix732.gif

    Vue3 调试钩子

    Vue3 为我们提供了两个可用于调试目的的钩子。

    1. onRenderTracked
    2. onRenderTriggered

    这两个事件都带有一个debugger event,此事件告诉你哪个操作跟踪了组件以及该操作的目标对象和键。

    onRenderTracked

    跟踪虚拟 DOM 重新渲染时调用。钩子接收 debugger event 作为参数。此事件告诉你哪个操作跟踪了组件以及该操作的目标对象和键。

    <div id="app">
      <button v-on:click="addToCart">Add to cart</button>
      <p>Cart({{ cart }})</p>
    </div>
    
    const app = Vue.createApp({
      data() {
        return {
          cart: 0
        }
      },
      renderTracked({ key, target, type }) {
        console.log({ key, target, type })
        /* 当组件第一次渲染时,这将被记录下来:
        {
          key: "cart",
          target: {
            cart: 0
          },
          type: "get"
        }
        */
      },
      methods: {
        addToCart() {
          this.cart += 1
        }
      }
    })
    
    app.mount('#app')
    

    renderTracked

    当虚拟 DOM 重新渲染为 triggered.Similarly 为renderTracked,接收 debugger event 作为参数。此事件告诉你是什么操作触发了重新渲染,以及该操作的目标对象和键。

    用法:

    <div id="app">
      <button v-on:click="addToCart">Add to cart</button>
      <p>Cart({{ cart }})</p>
    </div>
    
    const app = Vue.createApp({
      data() {
        return {
          cart: 0
        }
      },
      renderTriggered({ key, target, type }) {
        console.log({ key, target, type })
      },
      methods: {
        addToCart() {
          this.cart += 1
          /* 这将导致renderTriggered调用
            {
              key: "cart",
              target: {
                cart: 1
              },
              type: "set"
            }
          */
        }
      }
    })
    
    app.mount('#app')
    

    总结

    无论你选择使用选项API还是 组合API,不仅要知道要使用哪个生命周期挂钩,而且要知道为什么要使用它,这一点很重要。

    对于许多问题,可以使用多个生命周期钩子。但是最好知道哪个是最适合你用例的。无论如何,你都应该好好考虑一下,并有充分的理由去选择一个特定的生命周期钩子。

    我希望这能帮助大家更多地理解生命周期钩子以及如何在大家的项目中实现它们。

    ~完,我是刷碗智,我要去刷碗了,骨的白。


    代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug

    原文:https://learnvue.co/2020/12/how-to-use-lifecycle-hooks-in-vue3/

    交流

    文章每周持续更新,可以微信搜索「 大迁世界 」第一时间阅读和催更(比博客早一到两篇哟),本文 GitHub https://github.com/qq449245884/xiaozhi 已经收录,整理了很多我的文档,欢迎Star和完善,大家面试可以参照考点复习,另外关注公众号,后台回复福利,即可看到福利,你懂的。

    展开全文
  • matlab开发-PSDSXXFSTPloton的时间周期。从给定的双面PSD创建时间序列
  • % 导入图集为一个步态周期,且以步态跨度最大时为起始时刻 figure('NumberTitle','off','Name','数据库图集'); %%%% %%%% 从图集中读取所有图片 fileDir = ['gaitpic\Trainingset\cl',num2str(filnum),'\']; % ...
  • matlab开发-与周期路径一致的Dijkstraalgorithm。这个函数和附加的示例显示了从目录中查找最短路径(包括循环路径)
  • matlab导入excel代码囊袋 为什么选择sac2mat? Quadstar 32位软件非常有限,无法分析来自QMS测量的质谱。 可以将每个周期的数据从SAC文件导出到CSV文件,但是必须为每个周期保存。 拟议的代码sac2mat很大程度上基于...
  • matlab开发-计数周期从3到9个完全无向图。使用修剪的组合枚举计算简单无向图中3到9大小的所有循环。
  • matlab开发-分形时间周期分析的半方差方法和比例窗方差方法。分形时间序列分析的半方差法和比例窗方差法。
  • 离散太阳黑子信号的时域滤波及其周期性分析matlab代码,有注释,开始需自行导入数据文件
  • 针对相位差对检测结果的影响,提出正反导入的检测方法,该方法能有效克服由相位差造成的漏检现象。对仿真信号和故障轴承振动信号的检测效果表明,混沌振子结合集合经验模式分解降噪的方法能有效检测含在强噪声中周期...
  •  随着通信﹑电子类产品的市场竞争不断加剧,产品的生命周期在不断缩短,企业原有产品的升级及新产品的投放速度对该企业的生存和发展起到越来越关键的作用。而在制造环节,如何在生产中用更少的导入时间获得更高可...
  • 对于开发Android的朋友来说Activity的生命周期肯定不陌生,但是对于Dialog的生命周期就会有点困惑了,可能会问咋个Dialog还有生命周期呢?没错,Dialog不仅有生命周期而且会与Activity有密切的关联。相信用过Dialog...

    前言

            对于开发Android的朋友来说Activity的生命周期肯定不陌生,但是对于Dialog的生命周期就会有点困惑了,可能会问咋个Dialog还有生命周期呢?没错,Dialog不仅有生命周期而且会与Activity有密切的关联。相信用过Dialog的朋友肯定记得如何让Dialog消失的方法:就是调用dialog.cancle 或 dialog.dismiss()方法。OK,那么,下面我们先看一下Dialog 的六个生命周期。

    前言

    一、Dialog生命周期

    二、Activity上有Dialog的时候的生命周期

    三、封装对话框管理类


    一、Dialog生命周期

    • onCreate(),show(),onStart() ,cancel(),onDismiss(),Stop() 

    是不是看着很眼熟,当在对话框创建onCreate()后(仅执行一次创建),show()方法用于展示对话框,随后调用onStart(),当点击back键或点击外部会执行cancel(),如果调用dialog.dismiss()方法会执行onDismiss,对话框消失最后会执行Stop()。

     

    二、Activity上有Dialog的时候的生命周期

    Android 深刻理解Activity生命周期的作用及意义

    有些朋友可能会认为Activity被覆盖会处于onPause的生命周期,完全不可见即将销毁则处于onStop状态, 但是弹出Dialog覆盖时会不会这样呢?很简单的做个试验: 点击按钮弹出一个Dialog, 这时后面的Activity处于不完全可见的状态, 打印出Activity生命周期的变化。

    public class MainActivity extends AppCompatActivity {
     
        private Button button;
        private String TAG = "MainActivity";
     
        public void init(){
            button = findViewById(R.id.button);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    AlertDialog dialog = new AlertDialog.Builder(MainActivity.this)
                            .setIcon(R.mipmap.ic_launcher_round)
                            .setCancelable(false)
                            .setTitle("dialog")
                            .show();
                }
            });
        }
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            init();
        }
     
        protected void onStart(){
            Log.d(TAG,"onStart方法正在执行");
            super.onStart();
        }
     
        protected void onResume(){
            Log.d(TAG,"onResume方法正在执行");
            super.onResume();
        }
     
        protected void onPause(){
            Log.d(TAG,"onPause方法正在执行");
            super.onPause();
        }
     
        protected void onStop(){
            Log.d(TAG,"onStop方法正在执行");
            super.onStop();
        }
     
        protected void onDestroy(){
            Log.d(TAG,"onDestroy方法正在执行");
            super.onDestroy();
        }
    }
    

    程序打开后,点击弹框,生命周期显示是:onCreate() -> onStart() -> onResume 。这表明弹出的东西对后面Activity的生命周期并没有影响。

    官方文档我们可以看到: onPause():Called when the system is about to start resuming another activity. (启动另外一个Activity的时候才会进入onPause状态)

    Dialog实现的原理是windowmanager.addView();其实添加的是一个view。所以,我们弹出的Dialog对话框实际上是Activity的一个组件,Activity并不是不可见而是被一个布满屏幕的组件覆盖到最顶层,我们无法对其他内容进行操作,因此,Dialog不会影响Activity的生命周期的变化。

     

    如果在弹出对话框的Activity点击home键返回桌面,Activity生命周期会不会变化呢?当然会,会执行onPause() -> onStop() 。

    再次启动: onRestart() -> onStart() -> onResume()。(有没有Dialog生命周期都不会发生变化)

    三、封装对话框管理类

    通过对support v4/v7/v13的区别我们了解到v7最低兼容Android2.1版本的系统,所以我们使用Dialog可以这样导入:

    import android.support.v7.app.AlertDialog; 
    
     //对话框
        private static AlertDialog alertDialog;
    
        /**
         *  显示单独按钮的Dialog
         */
        public static void showSimpleDialog(Activity context, String title, String message , DialogInterface.OnClickListener clickListener) {
            AlertDialog.Builder builder =new AlertDialog.Builder(context);
            builder.setCancelable(true);
            builder.setTitle(title);
            builder.setMessage(message);
            //监听事件
            if (clickListener != null){
                builder.setPositiveButton("确认",clickListener);
            }else{
                builder.setNegativeButton("知道了",null);
            }
            alertDialog=builder.create();
            alertDialog.setCanceledOnTouchOutside(false);
            if(!((Activity) context).isFinishing()){
                alertDialog.show();
            }
        }
    
        /**
         *  显示双按钮Dialog
         */
        public static void showDoubleDialog(Activity context, String title, String message , DialogInterface.OnClickListener clickListener) {
            AlertDialog.Builder builder =new AlertDialog.Builder(context);
            builder.setCancelable(true);
            builder.setTitle(title);
            builder.setMessage(message);
            //监听事件
            if (clickListener != null){
                builder.setPositiveButton("确认",clickListener);
            }else{
                builder.setPositiveButton("确认",null);
            }
            builder.setNegativeButton("取消",null);
            alertDialog=builder.create();
            alertDialog.setCanceledOnTouchOutside(false);
            if(!context.isFinishing()){
                alertDialog.show();
            }
    
        }

    进度条对话框,需要自定义布局:

        //进度条
        private static Dialog progressDialog;
        /**
         * 显示进度条
         * @param context
         * @param msg
         */
        public static void showProgress(Activity context,String msg){
            if (progressDialog == null){
                progressDialog = new Dialog(context , R.style.loadingdialog);
                progressDialog.setContentView(R.layout.loading_dialog);
                progressDialog.setCanceledOnTouchOutside(false);
            } else if (progressDialog.isShowing()){
                progressDialog.dismiss();
            }
            if(!context.isFinishing())
            {
                progressDialog.show();
            }
    
        }
    
        /**
         * 关闭进度条
         */
        public static void dismissProgress(){
            if (progressDialog != null ){
                if (progressDialog.isShowing()){
                    progressDialog.dismiss();
                }
            }
        }

     

    其中布局:R.layout.loading_dialog:

     

     

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <LinearLayout
            android:layout_width="150dp"
            android:layout_height="130dp"
            android:layout_centerInParent="true"
            android:orientation="vertical"
            android:gravity="center"
            android:background="#ab0e0e0e">
    
            <ProgressBar
                android:id="@+id/pro"
                android:indeterminateTintMode="src_atop"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:indeterminateDrawable="@drawable/progressbar_bg"
                />
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:text="加载中..."/>
    
        </LinearLayout>
    
    </RelativeLayout>


    其中ProgressBar的Style.Theme: R.style.loadingdialog

     

       <style name="loadingdialog" parent="@android:style/Theme.Dialog">
            <item name="android:windowFrame">@null</item><!-- Dialog的边框,@null标识无 -->
            <item name="android:windowIsFloating">true</item><!--是否浮现在activity之上-->
            <item name="android:windowIsTranslucent">false</item><!--半透明-->
            <item name="android:windowNoTitle">true</item><!--无标题-->
            <item name="android:windowBackground">@color/transparent</item><!--背景透明-->
            <item name="android:backgroundDimEnabled">false</item><!--模糊-->
        </style>


    其中ProgressBar属性android:indeterminateDrawable="@drawable/progressbar_bg"

     

    <?xml version="1.0" encoding="utf-8"?>
    <animated-rotate
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:pivotX="50%" android:pivotY="50%"
        android:fromDegrees="0"
        android:toDegrees="360">
    
        <shape
            android:shape="ring"
            android:innerRadiusRatio="3"
            android:thicknessRatio="10"
            android:useLevel="false">
            <gradient
                android:type="sweep"
                android:useLevel="false"
                android:startColor="#ffa500"
                android:centerColor="#FF7121"
                android:centerY="0.50"
                android:endColor="#FFFF00" />
        </shape>
    
    </animated-rotate>

     

     


     

     

     

    展开全文
  • 江恩时间循环周期

    2018-09-12 18:18:49
    本书是以实战案例诠释江恩理论...本书用霍金的理论首先对“时间”为何物做出了解释,然后再导入循环和周期的定义,最后引出江恩的时间循环周期和圆形循环周期,并实际地运用于预测股票市场,指导投资者日常的具体操作。
  • 商业软件划分的网格导入OpenFOAM问题总结【终极】 openfoam自己带有网格划分功能blockMesh和snapHexMesh.前者可以生成块结构化网格,后者则基于表面网格文件(stl格式)自动生成复杂的网格。她还带有商业软件网格...
  • 在存储桶上设置生命周期策略,以在1天后删除文件 然后,在您的终端上执行以下操作: $ vault write secret/dsde/monster/ ${env} /biccn/terra-import-builder/env \ project= ${the-new-project} \ buck
  • 首先查一下自己的oracle的字符集   select * from v$nls_parameters;   ...alter session set nls_date_language='SIMPLIFIED CHINESE/...我是在Navicat里面测试一下有没有用,发现完全没问题,很开心。 ...
  • 之前的博文和视频都讲过 ILM 索引生命周期管理。但从近期的反馈和我自己的实战经验看,依然会有很多坑。现将我自己和大家遇到的常见坑汇集如下,希望能让后来小伙伴少走弯路。少啰嗦,直接上干货。...
  • 游戏中的生命周期

    千次阅读 2019-08-09 21:01:52
    生命周期一词,相信很多人都非常熟悉。当然,对于不同的行业,具体的生命周期的概念有所不同,但基本概念是一致的。按照一般的说法,生命周期的定义是:事物的成长都要经历发展、成长、成熟、衰退的过程。 严格说来...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 138,600
精华内容 55,440
关键字:

周期问题导入