精华内容
下载资源
问答
  • Spring 了解Bean的一生(生命周期)

    万次阅读 多人点赞 2018-04-25 22:29:00
    该篇博客就来了解IoC容器下Bean的一生吧,也可以理解为bean的生命周期。 首先你需要知道的知识 在IoC容器启动之后,并不会马上就实例化相应的bean,此时容器仅仅拥有所有对象的BeanDefinition(Bean...

    该篇博客就来了解IoC容器下Bean的一生吧,也可以理解为bean的生命周期。

    首先你需要知道的知识

    在IoC容器启动之后,并不会马上就实例化相应的bean,此时容器仅仅拥有所有对象的BeanDefinition(BeanDefinition:是容器依赖某些工具加载的XML配置信息进行解析和分析,并将分析后的信息编组为相应的BeanDefinition)。只有当getBean()调用时才是有可能触发Bean实例化阶段的活动

    为什么说有可能触发Bean实例化阶段?

    因为当对应某个bean定义的getBean()方法第一次被调用时,不管是显示的还是隐式的,Bean实例化阶段才会被触发,第二次被调用则会直接返回容器缓存的第一次实例化完的对象实例(因为默认是singleton单例,当然,这里的情况prototype类型的bean除外)

    该篇博客主要阐述

    1、Bean的一生过程
    2、Bean的后置处理器

    一、Bean的一生过程

    先来看以下的图(Bean的一生)

    这里写图片描述

    可以简述为以下九步

    • 实例化bean对象(通过构造方法或者工厂方法)
    • 设置对象属性(setter等)(依赖注入)
    • 如果Bean实现了BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。(和下面的一条均属于检查Aware接口)
    • 如果Bean实现了BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身
    • 将Bean实例传递给Bean的前置处理器的postProcessBeforeInitialization(Object bean, String beanname)方法
    • 调用Bean的初始化方法
    • 将Bean实例传递给Bean的后置处理器的postProcessAfterInitialization(Object bean, String beanname)方法
    • 使用Bean
    • 容器关闭之前,调用Bean的销毁方法

    先看一个最简单的一生(没有使用Bean的后置处理器)

    Student.java

    package com.linjie.cycle;
    
    import org.springframework.beans.factory.BeanNameAware;
    
    /**
     * @author LinJie
     * @Description:一个学生类(Bean),能体现其生命周期的Bean
     */
    public class Student implements BeanNameAware {
    	private String name;
    
    	//无参构造方法
    	public Student() {
    		super();
    	}
    
    	/** 设置对象属性
    	 * @param name the name to set
    	 */
    	public void setName(String name) {
    		System.out.println("设置对象属性setName()..");
    		this.name = name;
    	}
    	
    	//Bean的初始化方法
    	public void initStudent() {
    		System.out.println("Student这个Bean:初始化");
    	}
    	
    	//Bean的销毁方法
    	public void destroyStudent() {
    		System.out.println("Student这个Bean:销毁");
    	}
    	
    	//Bean的使用
    	public void play() {
    		System.out.println("Student这个Bean:使用");
    	}
    
    	/* 重写toString
    	 * @see java.lang.Object#toString()
    	 */
    	@Override
    	public String toString() {
    		return "Student [name = " + name + "]";
    	}
    
    	//调用BeanNameAware的setBeanName()
    	//传递Bean的ID。
    	@Override
    	public void setBeanName(String name) {
    		System.out.println("调用BeanNameAware的setBeanName()..." ); 
    	}
    	
    }
    

    测试类

    package com.linjie.cycle;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.AbstractApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * 测试类
     * @author LinJie
     * 
     */
    public class CycleTest {
        @Test
     	public void test() {
    		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    		Student student = (Student) context.getBean("student");
    		//Bean的使用
    		student.play();
    		System.out.println(student);
    		//关闭容器
    		((AbstractApplicationContext) context).close();
    	}
    }
    

    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 http://www.springframework.org/schema/beans/spring-beans.xsd">
     
       <!-- init-method:指定初始化的方法
            destroy-method:指定销毁的方法 -->
    		<bean id="student" class="com.linjie.cycle.Student" init-method="initStudent" destroy-method="destroyStudent">
    		<property name="name" value="LINJIE"></property>
    		</bean>
    </beans>
    

    控制台显示结果

    这里写图片描述

    可以在输出结果看出bean的一生,完全与之前的一生过程图相符(除了bean后置处理器部分),这里还需要提及的是在xml配置中的两个属性

    • init-method:指定初始化的方法
    • destroy-method:指定销毁的方法
    说到init-method和destroy-method,当然也要提及一下在< beans>的属性
    • default-init-method:为应用上下文中所有的Bean设置了共同的初始化方法
    • default-destroy-method:为应用上下文中所有的Bean设置了共同的销毁方法

    这里写图片描述


    二、Bean的后置处理器

    上面bean的一生其实已经算是对bean生命周期很完整的解释了,然而bean的后置处理器,是为了对bean的一个增强

    用法

    分别在Bean的初始化前后对Bean对象提供自己的实例化逻辑

    - 实现BeanPostProcessor接口
    	- postProcessBeforeInitialization方法
    	- postProcessAfterInitialization方法
    

    接上面的Student Demo

    Student.java

    package com.linjie.cycle;
    
    import org.springframework.beans.factory.BeanNameAware;
    
    /**
     * @author LinJie
     * @Description:一个学生类(Bean),能体现其生命周期的Bean
     */
    public class Student implements BeanNameAware {
    	private String name;
    
    	//无参构造方法
    	public Student() {
    		super();
    	}
    
    	/** 设置对象属性
    	 * @param name the name to set
    	 */
    	public void setName(String name) {
    		System.out.println("设置对象属性setName()..");
    		this.name = name;
    	}
    	
    	//Bean的初始化方法
    	public void initStudent() {
    		System.out.println("Student这个Bean:初始化");
    	}
    	
    	//Bean的销毁方法
    	public void destroyStudent() {
    		System.out.println("Student这个Bean:销毁");
    	}
    	
    	//Bean的使用
    	public void play() {
    		System.out.println("Student这个Bean:使用");
    	}
    
    	/* 重写toString
    	 * @see java.lang.Object#toString()
    	 */
    	@Override
    	public String toString() {
    		return "Student [name = " + name + "]";
    	}
    
    	//调用BeanNameAware的setBeanName()
    	//传递Bean的ID。
    	@Override
    	public void setBeanName(String name) {
    		System.out.println("调用BeanNameAware的setBeanName()..." ); 
    	}
    	
    }
    

    MyBeanPostProcessor.java(实现BeanPostProcessor接口)

    package com.linjie.cycle;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    
    /**
     * bean的后置处理器
     * 分别在bean的初始化前后对bean对象提供自己的实例化逻辑
     * postProcessAfterInitialization:初始化之后对bean进行增强处理
     * postProcessBeforeInitialization:初始化之前对bean进行增强处理
     * @author LinJie
     * 
     */
    public class MyBeanPostProcessor implements BeanPostProcessor {
    
    	//对初始化之后的Bean进行处理
    	//参数:bean:即将初始化的bean
    	//参数:beanname:bean的名称
    	//返回值:返回给用户的那个bean,可以修改bean也可以返回一个新的bean
    	@Override
    	public Object postProcessAfterInitialization(Object bean, String beanname) throws BeansException {
    		Student stu = null;
    		System.out.println("对初始化之后的Bean进行处理,将Bean的成员变量的值修改了");
    		if("name".equals(beanname) || bean instanceof Student) {
    			stu = (Student) bean;
    			stu.setName("Jack");
    		}
    		return stu;
    	}
    
    	//对初始化之前的Bean进行处理
    	//参数:bean:即将初始化的bean
    	//参数:beanname:bean的名称
    	//返回值:返回给用户的那个bean,可以修改bean也可以返回一个新的bean
    	@Override
    	public Object postProcessBeforeInitialization(Object bean, String beanname) throws BeansException {
    		System.out.println("对初始化之前的Bean进行处理,此时我的名字"+bean);
    		return bean;
    	}
    
    }
    

    测试类

    package com.linjie.cycle;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.AbstractApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * 测试类
     * @author LinJie
     * 
     */
    public class CycleTest {
        @Test
     	public void test() {
    		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    		Student student = (Student) context.getBean("student");
    		//Bean的使用
    		student.play();
    		System.out.println(student);
    		//关闭容器
    		((AbstractApplicationContext) context).close();
    	}
    }
    

    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 http://www.springframework.org/schema/beans/spring-beans.xsd">
       <!-- init-method:指定初始化的方法
            destroy-method:指定销毁的方法 -->
    		<bean id="student" class="com.linjie.cycle.Student" init-method="initStudent" destroy-method="destroyStudent">
    		<property name="name" value="LINJIE"></property>
    		</bean>
    		
    		<!-- 配置bean的后置处理器,不需要id,IoC容器自动识别是一个BeanPostProcessor -->
    		<bean class="com.linjie.cycle.MyBeanPostProcessor"></bean> 
    </beans>
    

    控制台显示结果

    这里写图片描述

    可以在applicationContext.xml中看到配置Bean后置处理器,不需要ID,只需要其全类名,因为IoC容器自动识别一个BeanPostProcessor

    #####在控制台显示结果可以看出,Bean的后置处理器强大之处,可以对Bean实现自己想要做的事情,比如我这里的Demo就是在postProcessAfterInitialization方法中将成员变量name偷偷修改了,最后输出的就是偷偷修改之后的值

    好了以上就是bean的一生,在控制台下将bean的一生映射出来,对理解bean的一生(生命周期)更加直观咯


    参考

    《Spring揭秘》
    《Spring IN ACTION》

    展开全文
  • flutter 生命周期

    万次阅读 2018-09-13 22:20:26
    前言:生命周期是一个组件加载到卸载的整个周期,熟悉生命周期可以让我们在合适的时机做该做的事情, flutter中的State生命周期和android以及React Native的生命周期类似。 先看一张生命周期的流程图: 大致...

    前言:生命周期是一个组件加载到卸载的整个周期,熟悉生命周期可以让我们在合适的时机做该做的事情,
    flutter中的State生命周期和android以及React Native的生命周期类似。

    先看一张生命周期的流程图:

    这里写图片描述
    大致可以分为3个阶段:

    • 初始化
    • 状态变化
    • 组件移除

    初始化

    State初始化时会依次执行 : 构造函数 > initState > didChangeDependencies > Widget build , 此时页面加载完成。

    然后我们看一下每个函数的意义:

    构造函数

    调用次数:1次

    这个函数严格意义上来讲不属于生命周期的一部分,因为这个时候State的widget属性为空,无法在构造函数中访问widget的属性 。但是构造函数必然是要第一个调用的。可以在这一部分接收前一个页面传递过来的数据。

    initState

    Called when this object is inserted into the tree.

    调用次数:1次

    当插入渲染树的时候调用,这个函数在生命周期中只调用一次。这里可以做一些初始化工作,比如初始化State的变量。

    didChangeDependencies

    Called when a dependency of this [State] object changes.

    • 初始化时,在initState()之后立刻调用
    • 当依赖的InheritedWidget rebuild,会触发此接口被调用

    这个函数会紧跟在initState之后调用,并且可以调用BuildContext.inheritFromWidgetOfExactType,那么BuildContext.inheritFromWidgetOfExactType的使用场景是什么呢?最经典的应用场景是

    new DefaultTabController(length: 3, child: new TabBar(
          tabs: [ "主页","订单","我的" ]
          .map( (data)=>new Text(data) ).toList(),
          
    

    TabBar本来需要定义一个TabController,但是在外面套一层DefaultTabController就不需要定义TabContrller了,看下源码:

    
    @override
      void didChangeDependencies() {
        super.didChangeDependencies();
        _updateTabController();
        _initIndicatorPainter();
      }
    
    void _updateTabController() {
        final TabController newController = widget.controller ?? DefaultTabController.of(context);
        ...
        }
    

    注意到这里DefaultTabController.of(context)

    static TabController of(BuildContext context) {
        final _TabControllerScope scope = context.inheritFromWidgetOfExactType(_TabControllerScope);
        return scope?.controller;
      }
    

    实际上就是调用BuildContext.inheritFromWidgetOfExactType,也就说在didChangeDependencies中,可以跨组件拿到数据。

    #运行时

    build

    调用次数:多次

    初始化之后开始绘制界面,当setState触发的时候会再次被调用

    didUpdateWidget

    Called whenever the widget configuration changes.

    祖先节点rebuild widget时调用 .当组件的状态改变的时候就会调用didUpdateWidget.

    理论上setState的时候会调用,但我实际操作的时候发现只是做setState的操作的时候没有调用这个方法。而在我改变代码hot reload时候会调用 didUpdateWidget 并执行 build…

    实际上这里flutter框架会创建一个新的Widget,绑定本State,并在这个函数中传递老的Widget。
    这个函数一般用于比较新、老Widget,看看哪些属性改变了,并对State做一些调整。

    需要注意的是,涉及到controller的变更,需要在这个函数中移除老的controller的监听,并创建新controller的监听。

    组件移除

    组件移除,例如页面销毁的时候会依次执行:deactivate > dispose

    deactivate

    Called when this object is removed from the tree.

    在dispose之前,会调用这个函数。实测在组件可见状态变化的时候会调用,当组件卸载时也会先一步dispose调用。

    dispose

    Called when this object is removed from the tree permanently.

    调用次数:1次

    一旦到这个阶段,组件就要被销毁了,这个函数一般会移除监听,清理环境。

    ##reassemble
    hot reload调用

    名称 状态
    initState 插入渲染树时调用,只调用一次
    didChangeDependencies state依赖的对象发生变化时调用
    didUpdateWidget 组件状态改变时候调用,可能会调用多次
    build 构建Widget时调用
    deactivate 当移除渲染树的时候调用
    dispose 组件即将销毁时调用

    实际场景

    假设我们从A页面跳转到B页面, 那么A,B页面的生命周期会是怎样的呢?

    B页面进入初始化状态,依次执行4个函数:构造函数 > initState > didChangeDependencies > Widget build , 此时页面加载完成,进入运行态。
    此时A页面依次执行deactivate > build函数。注意 此时A页面并未卸载。

    然后我们假设B页面只有一个按钮,点击B页面中的按钮,改变按钮的文字,会执行widget的build方法 ,(理论上也应该执行didUpdateWidget,但我这里没有)。

    这时,我们点击返回键从B页面返回到A页面。
    A页面重新显示,B页面开始卸载。
    那么A先执行deactivate > build , 然后B页面依次执行:deactivate > dispose
    此时A页面进入运行态,B页面移除。

    本次示例B页面代码:

    /*
     * Created by 李卓原 on 2018/9/13.
     * email: zhuoyuan93@gmail.com
     *
     */
    
    import 'package:flutter/material.dart';
    
    class NewsDetailPage extends StatefulWidget {
      @override
      State<StatefulWidget> createState() => NewsDetailState();
    }
    
    class NewsDetailState extends State<NewsDetailPage> {
      int text = 1;
    
      NewsDetailState() {
        print('构造函数');
      }
    
      @override
      void initState() {
        print('init state');
        super.initState();
      }
    
      @override
      void didChangeDependencies() {
        print('didChangeDependencies');
        super.didChangeDependencies();
      }
    
      @override
      Widget build(BuildContext context) {
        print('widget build');
    
        return Scaffold(
          body: Center(
            child: _loading(),
          ),
          appBar: AppBar(
            title: Text('咨询详情'),
          ),
        );
      }
    
      @override
      void didUpdateWidget(NewsDetailPage oldWidget) {
        print('组件状态改变:didUpdateWidget');
        super.didUpdateWidget(oldWidget);
      }
    
      @override
      void deactivate() {
        print('移除时:deactivate');
        super.deactivate();
      }
    
      @override
      void dispose() {
        print('移除时:dispose');
        super.dispose();
      }
    
      //预加载布局
      Widget _loading() {
        return Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            CircularProgressIndicator(
              strokeWidth: 1.0,
            ),
            Container(
              child: Text("正在加载"),
              margin: EdgeInsets.only(top: 10.0),
            )
          ],
        );
      }
    }
    
    
    

    Tips:

    下面内容来自咸鱼技术团队.

    • 当ListView中的item滚动出可显示区域的时候,item会被从树中remove掉,此item子树中所有的state都会被dispose,state记录的数据都会销毁,item滚动回可显示区域时,会重新创建全新的state、element、renderobject

    • 使用hot reload功能时,要特别注意state实例是没有重新创建的,如果该state中存在一下复杂的资源更新需要重新加载才能生效,那么需要在reassemble()添加处理,不然当你使用hot reload时候可能会出现一些意想不到的结果,例如,要将显示本地文件的内容到屏幕上,当你开发过程中,替换了文件中的内容,但是hot reload没有触发重新读取文件内容,页面显示还是原来的旧内容.

    • didChangeDependencies有两种情况会被调用。

    • 创建时候在initState 之后被调用

    • 在依赖的InheritedWidget发生变化的时候会被调用

    • 正常的退出流程中会执行deactivate然后执行dispose。但是也会出现deactivate以后不执行dispose,直接加入树中的另一个节点的情况。

    • 这里的状态改变包括两种可能:1.通过setState内容改变 2.父节点的state状态改变,导致孩子节点的同步变化。

    App生命周期

    需要指出的是如果想要知道App的生命周期,那么需要通过WidgetsBindingObserver的didChangeAppLifecycleState 来获取。通过该接口可以获取是生命周期在AppLifecycleState类中。常用状态包含如下几个:

    名称 状态
    resumed 可见并能响应用户的输入
    inactive 处在并不活动状态,无法处理用户响应
    paused 不可见并不能响应用户的输入,但是在后台继续活动中

    一个实际场景中的例子:

    在不考虑suspending的情况下:从后台切入前台生命周期变化如下: AppLifecycleState.inactive->AppLifecycleState.resumed;

    从前台压后台生命周期变化如下: AppLifecycleState.inactive->AppLifecycleState.paused;

    class _MyWalletScreenState extends State<MyWalletScreen>
        with WidgetsBindingObserver {
    
     @override
      void initState() {
        super.initState();
        WidgetsBinding.instance.addObserver(this);
      }
    
      @override
      void dispose() {
        WidgetsBinding.instance.removeObserver(this);
        super.dispose();
      }  
    
      void didChangeAppLifecycleState(AppLifecycleState state) async {
        if (state == AppLifecycleState.resumed) {
          getData();
        }
      }
    }
    

    记得注册和移除监听。

    展开全文
  • vue生命周期

    万次阅读 2020-09-28 09:18:11
    随着对 vue 的不断了解,会越来越发现它生命周期的重要性,只有了解了它的生命周期,才能在开发项目的时候在逻辑上的很好的判断什么时候该发生什么事件,即很好的控制页面。 一、什么是 vue 生命周期 Vue 实例从...

    随着对 vue 的不断了解,会越来越发现它生命周期的重要性,只有了解了它的生命周期,才能在开发项目的时候在逻辑上的很好的判断什么时候该发生什么事件,即很好的控制页面。

    一、什么是 vue 生命周期

    Vue 实例从创建到销毁的过程,就是生命周期。也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。下面是官网中的生命周期照片

    二、生命周期函数

    Vue 的生命周期总共分为8个阶段:创建前/后,载入前/后,更新前/后,销毁前/后。

    1、beforeCreate(创建前)

    表示实例完全被创建出来之前,vue 实例的挂载元素$el和数据对象 data 都为 undefined,还未初始化。

    2、created(创建后)

    数据对象 data 已存在,可以调用 methods 中的方法,操作 data 中的数据,但 dom 未生成,$el 未存在 。

    3、beforeMount(挂载前)

    vue 实例的 $el 和 data 都已初始化,挂载之前为虚拟的 dom节点,模板已经在内存中编辑完成了,但是尚未把模板渲染到页面中。data.message 未替换。

    4、mounted(挂载后)

    vue 实例挂载完成,data.message 成功渲染。内存中的模板,已经真实的挂载到了页面中,用户已经可以看到渲染好的页面了。实例创建期间的最后一个生命周期函数,当执行完 mounted 就表示,实例已经被完全创建好了,DOM 渲染在 mounted 中就已经完成了。

    5、beforeUpdate(更新前)

    当 data 变化时,会触发beforeUpdate方法 。data 数据尚未和最新的数据保持同步。

    6、updated(更新后)

    当 data 变化时,会触发 updated 方法。页面和 data 数据已经保持同步了。

    7、beforeDestory(销毁前)

    组件销毁之前调用 ,在这一步,实例仍然完全可用。

    8、destoryed(销毁后)

    组件销毁之后调用,对 data 的改变不会再触发周期函数,vue 实例已解除事件监听和 dom绑定,但 dom 结构依然存在。

    具体详细可以参考:https://segmentfault.com/a/1190000011381906

    展开全文
  • Servlet的生命周期

    万次阅读 多人点赞 2019-06-02 17:36:53
    Servlet的生命周期 servlet的生命周期就是从servlet出现到销毁的全过程。主要分为以下几个阶段: 加载类—>实例化(为对象分配空间)—>初始化(为对象的属性赋值)—>请求处理(服务阶段)—>销毁 服务器启动...

    Servlet的生命周期

    servlet的生命周期就是从servlet出现到销毁的全过程。主要分为以下几个阶段:
    加载类—>实例化(为对象分配空间)—>初始化(为对象的属性赋值)—>请求处理(服务阶段)—>销毁

    服务器启动时(web.xml中配置load-on-startup=1,默认为0)或者第一次请求该servlet时,就会初始化一个Servlet对象,也就是会执行初始化方法init(ServletConfig conf),该servlet对象去处理所有客户端请求,service(ServletRequest req,ServletResponse res)方法中执行,最后服务器关闭时,才会销毁这个servlet对象,执行destroy()方法。其中加载阶段无法观察,但是初始化、服务、销毁阶段是可以观察到的。

    在这里插入图片描述

    public class EmpServlet extends HttpServlet{
    	//初始化servlet,调用init方法
    	@Override
    	public void init() throws ServletException {
    		System.out.println("初始化时调用");
    	}
    	//开启服务
    	@Override
    	protected void service(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException {
    		System.out.println("开启服务时调用");
    	}
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		
    	}
    	//销毁时调用destory
    	@Override
    	public void destroy() {
    		System.out.println("销毁时调用");
    	}
    }
    

    在这里插入图片描述
    思考问题
    为什么创建的servlet是继承自httpServlet,而不是直接实现Servlet接口?

    解答:
    首先我们来看下源码,HttpServlet的继承结构
    在这里插入图片描述
    HttpServlet继承了GenericServlet,GenericServlet是一个通用的Servlet,那么他的作用是什么呢?大概的就是将实现Servlet接口的方法,简化编写servlet的步骤。
    GenericServlet的继承结构:
    在这里插入图片描述
    实现了Servlet接口和ServletConfig接口

    Servlet接口的内容

    public interface Servlet {
    	void init(ServletConfig var1) throws ServletException;
    
    	ServletConfig getServletConfig();
    
    	void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
    
    	String getServletInfo();
    
    	void destroy();
    }
    

    从这里可以看到,Servlet生命周期的三个关键方法,init、service、destroy。还有另外两个方法,一个getServletConfig()方法来获取ServletConfig对象,ServletConfig对象可以获取到Servlet的一些信息,ServletName、ServletContext、InitParameter、InitParameterNames、通过查看ServletConfig这个接口就可以知道

    public interface ServletConfig {
    	String getServletName();
    
    	ServletContext getServletContext();
    
    	String getInitParameter(String var1);
    
    	Enumeration<String> getInitParameterNames();
    }
    

    其中ServletContext对象是servlet上下文对象,功能有很多,获得了ServletContext对象,就能获取大部分我们需要的信息,比如获取servlet的路径,等方法。

    到此,就知道了Servlet接口中的内容和作用,总结起来就是,三个生命周期运行的方法,获取ServletConfig,而通过ServletConfig又可以获取到ServletContext。而GenericServlet实现了Servlet接口后,也就说明我们可以直接继承GenericServlet,就可以使用上面我们所介绍Servlet接口中的那几个方法了,能拿到ServletConfig,也可以拿到ServletContext,不过那样太麻烦,不能直接获取ServletContext,所以GenericServlet除了实现Servlet接口外,还实现了ServletConfig接口,那样,就可以直接获取ServletContext了。

    在这里插入图片描述
    上图我们观察到,init方法存在两个,一个带参,一个无参

    private transient ServletConfig config;
    public void init(ServletConfig config) throws ServletException {
    		this.config = config;
    		this.init();
    	}
    
    	public void init() throws ServletException {
    	}
    	public ServletConfig getServletConfig() {
    		return this.config;
    	}
    

    通过这几个方法一起来讲解,首先看init(ServletConfig config)方法,因为只有init(ServletConfig config)中带有ServletConfig对象,为了方便能够在其他地方也能直接使用ServletConfig对象,而不仅仅局限在init(ServletConfig config)方法中,所以创建一个私有的成员变量config,在init(ServletConfig config)方法中就将其赋值给config,然后通过getServletConfig()方法就能够获取ServletConfig对象了,这个可以理解,但是在init(ServletConfig config)中,158行,还调用了一个init()方法,并且这个init()方法是空的,什么读没有,这是为什么呢?这个原因是为了防止一件事情,当我们需要在init方法中做一点别的事情,我们想到的方法就是继承GenericServlet并且重写了init(ServletConfig config)方法,这样依赖,就破坏了原本在GenericServlet类中init(ServletConfig config)写的代码了,也就是在GenericServlet类中的成员变量config会一直是null,无法得到赋值,因为被重写了,就不会在执行GenericServlet中init(ServletConfig config)方法中的代码。要想赋值,就必须在重写的init(ServletConfig config)方法中调用父类的init(ServletConfig config)方法,也就是super.init(ServletConfig config),这样一来,就很不方便,怕有时候会忘了写这句代码,所以在GenericServlet类中增加一个init()方法,以后需要在init方法中需要初始化别的数据,只需要重写init()这个方法,而不需要去覆盖init(ServletConfig config)这个方法,这样设计,就好很多,不用在管init(ServletConfig config)这个其中的内容了。也不用出现其他的问题。

    总结:
    Servlet的生命周期分为:加载阶段、实例化阶段、初始化阶段、服务阶段、销毁阶段。上面我们说了servlet默认是第一次被访问的时候初始化的,这种情况当用户要使用的时候才创建,也可以在服务器一启动的时候就创建好servlet(这种方式一般不用),要实现这样的操作需要进行配置,在web.xml中进行配置
    在这里插入图片描述

    展开全文
  • Vue的生命周期钩子函数介绍

    万次阅读 多人点赞 2019-05-11 22:45:23
    Vue的生命周期钩子函数介绍 vue生命周期共分为四个阶段 一:实例创建 二:DOM渲染 三:数据更新 四:销毁实例 共有八个基本钩子函数 1.beforeCreate --创建前 触发的行为:vue实例的挂载元素$el和数据对象data都为...
  • 微信小程序生命周期可分为应用生命周期、页面生命周期和组件生命周期,本文结合微信官方文档浅析微信小程序的应用生命周期。从注册一个小程序生命周期开始讲起,到一些关于开发的小经验。
  • 一、php生命周期(5块) 模块初始化阶段 --- php_module_startup() 请求初始化阶段 --- php_request_startup() 执行脚本阶段 --- php_execute_script() 请求关闭阶段 --- php_request_shutdown() 模块关闭阶段 --- ...
  • 什么叫生命周期,servlet的生命周期?jsp的生命周期生命周期:就是类的产生到销毁的过程。servlet的生命周期:加载并实例化 –&gt; 初始化 –&gt; 应用阶段(请求处理) –&gt; 销毁创建 Servlet 实例...
  • 1.项目生命周期的阶段之间可能相互交叉,而产品生命周期的阶段通常不相互交叉; 项目生命周期:项目初始->项目计划->项目执行控制->项目结束; 产品生命周期:投入期->成长期->饱和期->衰退期;...
  • 1. 生命周期 App(全局) 位置:项目根目录app.js文件 App({ onLaunch (options) { // console.log('小程序初始化') }, onShow(options) { console.log('监听小程序启动或切前台') }, onHide() { ...
  • vue生命周期函数 beforeCreate (创建前) created (创建后) beforeMount (挂载前) mounted (挂载后) beforeUpdate (数据更新前) updated (数据更新后) beforeDestroy (销毁前) destroyed (销毁后) 详情传送门 ...
  • vue生命周期钩子,vue生命周期钩子,vue生命周期钩子

    千次阅读 多人点赞 2018-07-14 14:53:35
    vue 的生命周期11个钩子函数是按照以下的顺序来的 :(不可逆转哦,第11个除外) 一. 组件创建前后 1.beforeCreate 2.created 如,写一个子组件,然后挂在到父组件,在子组件中,console.log 子组件中的 data...
  • react的生命周期钩子函数

    万次阅读 2019-04-22 08:23:35
    掌握单词后会更好理解生命周期: constructor ------构造函数 component ------组件 will ------将要 get ------得到 default ------默认值 initial ------最初的 unsafe ...
  • vue生命周期和react生命周期对比。

    千次阅读 2019-07-06 18:04:03
    指的是组件从初始化开始到结束的过程 或者是生命周期是描述组件从开始到结束的过程,每个组件都具有生命周期,都对组件通过生命周期给予的钩子函数进行管理。 钩子函数 指的是系统某些状态和参数发生改变的时候,...
  • 如何理解预测型生命周期、迭代和增量型生命周期和适应型生命周期?预测性生命周期迭代和增量型生命周期适应性生命周期(变化驱动方法或敏捷方法) 预测性生命周期 预测性生命周期生命周期的特点是确定性(项目开发...
  • 博主声明: 转载请在开头附加本文链接及作者信息,并标记为转载。... 在学习 Android 时候,通常一开始学习的都是它的生命周期,谁让我们第一个创建的就是 MainActivity 类呢。学习 Activity 就要从它...
  • Spring中bean的作用域与生命周期

    万次阅读 多人点赞 2017-06-17 22:29:18
    在Spring中,那些组成应用程序的主体及由Spring IoC容器所管理的对象,被称之为bean。简单地讲,bean就是由IoC容器初始化、装配及管理的对象,除此之外,bean就与应用程序中的其他对象没有什么区别了。...
  • 预测性生命周期生命周期的特点是确定性(项目开发时间确定、项目开发成本确定),成熟性(公司的产品已经很成熟了),规模性(项目已经具有一定规模了),可以尽早时间确定项目范围及所需的时间、成本。...
  • 理解Fragment生命周期

    万次阅读 多人点赞 2012-11-29 14:33:01
    官网帮助文档链接:  ... 主要看两张图,和跑代码 一,Fragment的生命周    二,与Activity生命周期的对比   场景演示 : 切换到该Fragment 11-29 14:26:35.095: D/AppListFragmen
  • Vue生命周期详解

    千次阅读 多人点赞 2020-06-25 11:19:34
    一、生命周期流程图详解 1.beforeCreate、Created 2.编辑模板过程 3.beforeMount、Mounted 4.beforeUpdate、Updated 5.beforeDestroy、Destroyed 二、生命周期代码 1.父子组件加载生命周期 2.父子组件更新...
  • Maven第六讲Maven第六讲生命周期maven中生命周期详解clean生命周期default生命周期site生命周期mvn命令和生命周期案例 Maven第六讲 项目pom.xml中,有下面这样一段依赖: <dependencies> <dependency> ...
  • Uni-app页面生命周期和应用生命周期

    千次阅读 2019-06-13 09:54:51
    Uni-app页面生命周期和应用生命周期 (V1.00版本)2019-6-13 学习任何框架必须将其生命周期了然于胸. uni-app支持如下页面生命周期函数: onLoad 监听页面加载,其参数为上个页面传递的数据,参数类型为object(用于...
  • 生命周期,有页面生命周期,这个应用生命周期 相当于一个人从生到死有什么 生命周期可以利用很多 运行顺利 onLoad :({ }); onShow: ({ }); 当用户操作的时候会自动触发相应函数 onReady: ({}); onUnload: ({});...
  • 使用vue框架,需要在合适的时机做合适的事情,了解了vue对象的生命周期和钩子函数,才能知道,哪些事情应该咋哪个函数里做。 一、vue的生命周期的理解 生命周期 用人举例说明: 生命周期就是一个人的一生,此处...
  • Servlet生命周期

    千次阅读 多人点赞 2019-03-05 20:14:55
    Servlet生命周期
  • 由华为出品、我国完全自主知识产权的HarmonyOS是一款“面向未来”、面向全场景(移动办公、运动健康、社交通信、媒体娱乐等)的...就像每个Android程序员都是从Activity的生命周期开始学习Android开发的,我们转型Harmo
  • java对象生命周期和类生命周期

    万次阅读 2018-01-05 15:04:13
    java对象生命周期对象的整个生命周期大致可以分为7个阶段:创建阶段(Creation)、应用阶段(Using)、不可视阶段(Invisible)、不可到达阶段(Unreachable)、可收集阶段(Collected)、终结阶段(Finalized)与...
  • 1.页面生命周期 StatelessWidget只有createElement和build的生命周期 StatefulWidget: 初始化周期: createState,initState 更新期间: didChangeDependencies,build, didUpdateWidget 销毁期: ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 170,499
精华内容 68,199
关键字:

生命周期