一、Bean的基础知识

1.在xml配置文件中,bean的标识(id 和 name)

id:指定在benafactory中管理该bean的唯一的标识。name可用来唯一标识bean 或给bean起别名。

[html] view
plain
copy

  1. <bean id="helloWorld" class="com.name.HelloWorld">
  2. ........
  3. <span style="color:#000000;"> </bean></span>

2.bean的class

class属性指定了bean的来源,即bean的实际路径。注意要指定全路径,而不可只写类名。

3.Singleton的使用

在spring中,bean可被定义为2中部署模式中的一种。singleton和prototype模式。

singloeton:只有一个共享的实例存在,所有对这个bean的请求都会返回这个唯一实例。

prototype:对这个bean的每次请求都会都会创建一个新的bean实例。根据已经存在的bean而clone出来的bean。默认为singleton模式。

改写成prototype模式写法如下:

[html] view
plain
copy

  1. <bean id="student3" class="com.mucfc.beanfactory.Student" scope="prototype">
  2. .......
  3. </bean>

4.bean的属性

spring中,bean的属性值有2种注入方式。setter注入和构造函数注入。

setter注入是在调用无参的构造函数或无参的静态工厂方法实例化配置文档中定义的bean之后,通过调用bean上的setter方法实现的。

构造函数的依赖注入是通过调用带有很多参数的构造方法实现的,每个参数表示一个对象或者属性。

这里不懂看此文

5.对属性null值的处理

[html] view
plain
copy

  1. <bean id="student5" class="com.mucfc.beanfactory.Student">
  2. <property name="std_name">
  3. <value></value>
  4. </property>
  5. <property name="std_id">
  6. <value>2005</value>
  7. </property>
  8. </bean>

或者

[html] view
plain
copy

  1. <bean id="student5" class="com.mucfc.beanfactory.Student">
  2. <property name="std_name">
  3. <value/>
  4. </property>
  5. <property name="std_id">
  6. <value>2005</value>
  7. </property>
  8. </bean>

以上等同于this.std_name=null

6.使用依赖depends-on

此属性可在使用该bean之前,强制初始化一个或多个bean的初始化。例如

[html] view
plain
copy

  1. <bean id="school" class="com.mucfc.beanfactory.School"
  2. depends-on="student6">
  3. <property name="student" ref="student6" />
  4. </bean>

其中student6如下:

[html] view
plain
copy

  1. <bean id="student6" class="com.mucfc.beanfactory.Student">
  2. <property name="std_name" value="水水" />
  3. <property name="std_id" value="3009" />
  4. </bean>

7.指定bean引用

[html] view
plain
copy

  1. <property name=" xxx" ref="yyyy "/>

或者

[html] view
plain
copy

  1. <property name="xxxx">
  2. <ref bean="yyt"/>
  3. <property/>

8、ref local指定同一个xml文件中的引用

二、bean的生命周期

                                                                                                beanfactory中bean的生命周期图

2.1 实例bean

1.当调用者通过getBean(beanName)向容器请求某一个Bean时,如果容器注册了org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor接口,在实例化Bean之前,将调用接口的postProcessBeforeInstantiation()方法;

2.根据配置情况调用Bean构造函数或工厂方法实例化Bean;

3.如果容器注册了InstantiationAwareBeanPostProcessor接口,在实例化Bean之后,调用该接口的postProcessAfterInstantiation()方法,可在这里对已经实例化的对象进行一些"梳妆打扮";

4.如果Bean配置了属性信息,容器在这一步着手将配置值设置到Bean对应的属性中,不过在设置每个属性之前将先调用InstantiationAwareBeanPostProcessor接口的postProcessPropertyValues()方法;



2.2 初始化和使用bean

1:BeanNameAware的setBeanName():

如果Bean类有实现org.springframework.beans.BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。

2:BeanFactoryAware的setBeanFactory():

如果Bean类有实现org.springframework.beans.factory.BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身。

3:BeanPostProcessors的ProcessBeforeInitialization()

如果有org.springframework.beans.factory.config.BeanPostProcessors和Bean关联,那么其postProcessBeforeInitialization()方法将被将被调用。

4:initializingBean的afterPropertiesSet():

如果Bean类已实现org.springframework.beans.factory.InitializingBean接口,则执行他的afterProPertiesSet()方法

5:Bean定义文件中定义init-method:

可以在Bean定义文件中使用"init-method"属性设定方法名称例如:

如果有以上设置的话,则执行到这个阶段,就会执行initBean()方法

6:BeanPostProcessors的ProcessaAfterInitialization()

如果有任何的BeanPostProcessors实例与Bean实例关联,则执行BeanPostProcessors实例的ProcessaAfterInitialization()方法

BeanPostProcessor后处理器定义了两个方法:

        其一是postProcessBeforeInitialization()在第8步调用;其二是Object postProcessAfterInitialization(Object bean, String beanName)方法,这个方法在此时调用,容器再次获得对Bean进行加工处理的机会;

        如果在<bean>中指定Bean的作用范围为scope="prototype",将Bean返回给调用者,调用者负责Bean后续生命的管理,Spring不再管理这个Bean的生命周期。如果作用范围设置为scope="singleton",则将Bean放入到Spring IoC容器的缓存池中,并将Bean引用返回给调用者,Spring继续对这些Bean进行后续的生命管理;

2.2 销毁bean

此时,Bean已经可以被应用系统使用,并且将保留在BeanFactory中知道它不在被使用。有两种方法可以将其从BeanFactory中删除掉

1:DisposableBean的destroy()

在容器关闭时,如果Bean类有实现org.springframework.beans.factory.DisposableBean接口,则执行他的destroy()方法

2:Bean定义文件中定义destroy-method

在容器关闭时,可以在Bean定义文件中使用"destroy-method"属性设定方法名称,例如:

如果有以上设定的话,则进行至这个阶段时,就会执行destroy()方法,如果是使用ApplicationContext来生成并管理Bean的话则稍有不同,使用ApplicationContext来生成及管理Bean实例的话,在执行BeanFactoryAware的setBeanFactory()阶段后,若Bean类上有实现org.springframework.context.ApplicationContextAware接口,则执行其setApplicationContext()方法,接着才执行BeanPostProcessors的ProcessBeforeInitialization()及之后的流程。

三、Beanfactory中bean生命周期实例

下面我们来看看一个实例吧,自己新建一个工程,导入需要的Spring包,然后建立如下Worker.java(这里是bean初始化和使用时会用到的函数 )

[java] view
plain
copy

  1. package com.mucfc.beanlive;
  2. import org.springframework.beans.BeansException;
  3. import org.springframework.beans.factory.BeanFactory;
  4. import org.springframework.beans.factory.BeanFactoryAware;
  5. import org.springframework.beans.factory.BeanNameAware;
  6. import org.springframework.beans.factory.DisposableBean;
  7. import org.springframework.beans.factory.InitializingBean;
  8. //①管理Bean生命周期的接口
  9. public class Worker implements BeanFactoryAware,BeanNameAware,InitializingBean,DisposableBean{
  10. private String name;
  11. private String workType;
  12. private int salary;
  13. public BeanFactory beanFactory;
  14. private String beanName;
  15. public void Worker(){
  16. System.out.println("调用worker()构造函数");
  17. }
  18. public String getName() {
  19. return name;
  20. }
  21. public void setName(String name) {
  22. this.name = name;
  23. }
  24. public String getWorkType() {
  25. return workType;
  26. }
  27. public void setWorkType(String workType) {
  28. this.workType = workType;
  29. }
  30. public int getSalary() {
  31. return salary;
  32. }
  33. public void setSalary(int salary) {
  34. this.salary = salary;
  35. }
  36. public void printInfo() {
  37. System.out.println("name:" + name + ";workType:" + workType + ";salary:"
  38. + salary);
  39. }
  40. //⑤DisposableBean接口方法
  41. @Override
  42. public void destroy() throws Exception {
  43. System.out.println("----------------销毁bean----------------------");
  44. System.out.println("调用DisposableBean.destroy()。");
  45. }
  46. //④InitializingBean接口方法
  47. @Override
  48. public void afterPropertiesSet() throws Exception {
  49. System.out.println("调用InitializingBean.afterPropertiesSet()。");
  50. }
  51. //③BeanNameAware接口方法
  52. @Override
  53. public void setBeanName(String arg0) {
  54. System.out.println("----------------初始化bean----------------------");
  55. System.out.println("调用BeanNameAware.setBeanName()。");
  56. this.beanName = arg0;
  57. }
  58. //②BeanFactoryAware接口方法
  59. @Override
  60. public void setBeanFactory(BeanFactory arg0) throws BeansException {
  61. System.out.println("调用BeanFactoryAware.setBeanFactory()。");
  62. this.beanFactory = arg0;
  63. }
  64. //⑥通过<bean>的init-method属性指定的初始化方法
  65. public void myInit() {
  66. System.out.println("调用init-method所指定的myInit(),将salary设置为600。");
  67. this.salary = 600;
  68. }
  69. //⑦通过<bean>的destroy-method属性指定的销毁方法
  70. public void myDestroy() {
  71. System.out.println("调用destroy-method所指定的myDestroy()。");
  72. }
  73. }

Worker类在②、③、④、⑤处实现了BeanFactoryAware、BeanNameAware、InitializingBean、DisposableBean这些Bean级的生命周期控制接口;在⑥和⑦处定义了myInit()和myDestroy()方法,以便在配置文件中通过init-method和destroy-method属性定义初始化和销毁方法。

MyInstantiationAwareBeanPostProcessor通过扩展InstantiationAwareBeanPostProcessor适配器InstantiationAwareBeanPostProcessorAdapter提供实现:

(这是实例化bean时会用到的函数)

[java] view
plain
copy

  1. package com.mucfc.beanlive;
  2. import java.beans.PropertyDescriptor;
  3. import org.springframework.beans.BeansException;
  4. import org.springframework.beans.PropertyValues;
  5. import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
  6. public class MyInstantiationAwareBeanPostProcessor extends
  7. InstantiationAwareBeanPostProcessorAdapter {
  8. // ①接口方法:在实例化Bean前进行调用
  9. public Object postProcessBeforeInstantiation(Class beanClass,
  10. String beanName) throws BeansException {
  11. System.out.println("----------------实例化bean----------------------");
  12. // ①-1仅对容器中worker Bean进行处理
  13. if ("worker".equals(beanName)) {
  14. System.out
  15. .println("InstantiationAware BeanPostProcessor. postProcess BeforeInstantiation");
  16. }
  17. return null;
  18. }
  19. // ②接口方法:在实例化Bean后调用
  20. public boolean postProcessAfterInstantiation(Object bean, String beanName)
  21. throws BeansException {
  22. // ②-1仅对容器中car Bean进行处理
  23. if ("worker".equals(beanName)) {
  24. System.out
  25. .println("InstantiationAware BeanPostProcessor.postProcess AfterInstantiation");
  26. }
  27. return true;
  28. }
  29. // ③接口方法:在设置某个属性时调用
  30. public PropertyValues postProcessPropertyValues(PropertyValues pvs,
  31. PropertyDescriptor[] pds, Object bean, String beanName)
  32. throws BeansException {
  33. // ③-1仅对容器中wroker Bean进行处理,还可以通过pdst入参进行过滤,
  34. // 仅对car的某个特定属性时进行处理。
  35. if ("worker".equals(beanName)) {
  36. System.out
  37. .println("Instantiation AwareBeanPostProcessor.postProcess PropertyValues");
  38. }
  39. return pvs;
  40. }
  41. }

在MyInstantiationAwareBeanPostProcessor中,我们通过过滤条件仅对work Bean进行处理,而对其他的Bean一概视而不见。

此外,我们还提供了一个BeanPostProcessor实现类,在该实现类中,我们也只对work Bean进行处理,对配置文件所提供的属性设置值进行判断,并执行相应的"补缺补漏"的操作:

BeanPostProcessor实现类(这里是bean初始化和使用时会用到的函数 )

[java] view
plain
copy

  1. package com.mucfc.beanlive;
  2. import org.springframework.beans.BeansException;
  3. import org.springframework.beans.factory.config.BeanPostProcessor;
  4. public class MyBeanPostProcessor implements BeanPostProcessor{
  5. @Override
  6. public Object postProcessAfterInitialization(Object bean, String beanName)
  7. throws BeansException {
  8. if(beanName.equals("worker")){
  9. Worker worker = (Worker)bean;
  10. if(worker.getWorkType() == null){
  11. System.out.println("调用BeanPostProcessor.postProcess AfterInitialization(),  getWorkType为空,设置为默认临时工");
  12. worker.setWorkType("临时工");
  13. }
  14. }
  15. return bean;
  16. }
  17. @Override
  18. public Object postProcessBeforeInitialization(Object bean, String beanName)
  19. throws BeansException {
  20. if(beanName.equals("worker")){
  21. Worker worker = (Worker)bean;
  22. if(worker.getSalary() >= 1000){
  23. System.out.println("调用BeanPostProcessor.postProcess BeforeInitialization(), 将salary调整为800。");
  24. worker.setSalary(800);
  25. }
  26. }
  27. return bean;
  28. }
  29. }

在MyBeanPostProcessor类的postProcessBeforeInitialization()方法中,我们首先判断处理的Bean是否名为worker,如果是,进一步判断该Bean的workerType属性是否为空,如果为空,将该属性设置为"临时工"。在postProcessAfterInitialization()方法中,我们也是只对名为woker的Bean进行处理,判断其salary是否超过最大速度1000,如果超过,将其设置为800。(黑心老板啊!!!!!)

至于如何将MyInstantiationAwareBeanPostProcessor和MyBeanPostProcessor这两个后处理器注册到BeanFactory容器中

现在,我们在Spring配置文件中定义Car的配置信息,如代码清单3 29所示:

然后就是beans.xml

[html] view
plain
copy

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
  5. <bean id="worker" class="com.mucfc.beanlive.Worker"
  6. init-method="myInit"
  7. destroy-method="myDestroy"
  8. p:name="小强"
  9. p:salary="1000"
  10. />
  11. </beans>

使用方法:

[java] view
plain
copy

  1. package com.mucfc.beanlive;
  2. import org.springframework.beans.factory.BeanFactory;
  3. import org.springframework.beans.factory.config.ConfigurableBeanFactory;
  4. import org.springframework.beans.factory.xml.XmlBeanFactory;
  5. import org.springframework.core.io.ClassPathResource;
  6. import org.springframework.core.io.Resource;
  7. public class Test {
  8. private static void LifeCycleInBeanFactory(){
  9. //①下面两句装载配置文件并启动容器
  10. Resource res = new ClassPathResource("beans.xml");
  11. BeanFactory bf = new XmlBeanFactory(res);
  12. //②向容器中注册MyBeanPostProcessor后处理器
  13. ((ConfigurableBeanFactory)bf).addBeanPostProcessor(new MyBeanPostProcessor());
  14. //③向容器中注册MyInstantiationAwareBeanPostProcessor后处理器
  15. ((ConfigurableBeanFactory)bf).addBeanPostProcessor(
  16. new MyInstantiationAwareBeanPostProcessor());
  17. //④第一次从容器中获取worker,将触发容器实例化该Bean,这将引发Bean生命周期方法的调用。
  18. Worker worker1 = (Worker)bf.getBean("worker");
  19. System.out.println("第一次从容器中获取worker");
  20. worker1.printInfo();
  21. System.out.println("修改第一次从容器中获取worker的workType");
  22. worker1.setWorkType("正式工");
  23. System.out.println("第一次从容器中获取worker(修改过后的)");
  24. worker1.printInfo();
  25. //⑤第二次从容器中获取worker,直接从缓存池中获取
  26. System.out.println("第二次从容器中获取worker");
  27. Worker worker2= (Worker)bf.getBean("worker");
  28. worker2.printInfo();
  29. //⑥查看worker1和worker2是否指向同一引用
  30. System.out.println("查看worker1和worker2是否指向同一引用    ");
  31. System.out.println("worker1==worker2:"+(worker1==worker2));
  32. //⑦关闭容器
  33. ((XmlBeanFactory)bf).destroySingletons();
  34. }
  35. public static void main(String[] args) {
  36. LifeCycleInBeanFactory();
  37. }
  38. }

输出结果:

图片看不清的话,看文字吧:

四月 07, 2015 3:43:54 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions

信息: Loading XML bean definitions from class path resource [beans.xml]

----------------实例化bean----------------------

InstantiationAware BeanPostProcessor. postProcess BeforeInstantiation

InstantiationAware BeanPostProcessor.postProcess AfterInstantiation

Instantiation AwareBeanPostProcessor.postProcess PropertyValues

----------------初始化bean----------------------

调用BeanNameAware.setBeanName()。

调用BeanFactoryAware.setBeanFactory()。

调用BeanPostProcessor.postProcess BeforeInitialization(), 将salary调整为800。

调用InitializingBean.afterPropertiesSet()。

调用init-method所指定的myInit(),将salary设置为600。

调用BeanPostProcessor.postProcess AfterInitialization(),  getWorkType为空,设置为默认临时工

第一次从容器中获取worker

name:小强;workType:临时工;salary:600

修改第一次从容器中获取worker的workType

第一次从容器中获取worker(修改过后的)

name:小强;workType:正式工;salary:600

第二次从容器中获取worker

name:小强;workType:正式工;salary:600

查看worker1和worker2是否指向同一引用    

worker1==worker2:true

四月 07, 2015 3:43:54 下午 org.springframework.beans.factory.xml.XmlBeanFactory destroySingletons

信息: Destroying singletons in org.springframework.beans.factory.xml.XmlBeanFactory@16905e: defining beans [worker]; root of factory hierarchy

----------------销毁bean----------------------

调用DisposableBean.destroy()。

调用destroy-method所指定的myDestroy()。

我们可以看到第二次获取worker时,直接从容器的缓存中获取,它们两个的指向的是同一个引用!切记!

四、ApplicationContext与beanfactory的区别

从ApplicationContext应用上下文容器中获取bean和从bean工厂容器中获取bean的区别?
具体案例:
1、从ApplicationContext中获取bean

ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
当我们去实例化beans.xml,该文件中配置的bean被实例化,(该bean的scope是singleton(单例))
2、如果我们使用beanfactory去获取bean,当你只是实例化该容器,那么容器的bean不被实例化,只有当你去使用getBean某个bean时(感谢hemi1995指出错别字),才会实时的创建
BeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
factory.getBean("student");

结论:
1、如果使用ApplicationContext,则配置的bean如果是singleton(单例)不管你用不用都被实例化,好处就是可以预先加载,坏处是浪费内存,
2、如果是用BeanFactory,则当你实例化该对象的时候,配置的bean不会被马上实例化,当你使用的时候才会被实例化(就像延缓加载机制)好处就是节约内存,缺点是速度回降慢,
3规则:一般没有特殊的要求,应当使用ApplicationContext完成(90%以上的项目)

使用ApplicationContext三种经常用到的实现:
1、ClassPathXmlApplicationContext->从类路径加载
2、FileSystemXmlApplicationContext->从文件系统加载
举例:ApplicationContext ac = newFIleSystemXmlApplicationContext("C:\Users\Workspaces\MyEclipse 
8.5\myspring\src\com\zqx\inter\beans.xml");
3、XmlWebApplicationContext->从web系统中加载(当tomcat启动的时候加载)

Spring学习总结(6)——Spring之核心容器bean的更多相关文章

  1. Spring学习1:Spring基本特性

    http://longliqiang88.github.io/2015/08/14/Spring%E5%AD%A6%E4%B9%A01%EF%BC%9ASpring%E5%9F%BA%E6%9C%AC ...

  2. Spring学习笔记之 Spring IOC容器(一)之 实例化容器,创建JavaBean对象,控制Bean实例化,setter方式注入,依赖属性的注入,自动装配功能实现自动属性注入

    本节主要内容:       1.实例化Spring容器示例    2.利用Spring容器创建JavaBean对象    3.如何控制Bean实例化    4.利用Spring实现bean属性sett ...

  3. Spring之核心容器bean

    摘要:Spring的核心容器实现了Ioc,其目 的是提供一种无侵入式的框架.在本文中,首先讲解了Spring的基础bean的相关知识,然后介绍了Spring是如何对bean进行管理的. 在Spring ...

  4. spring学习笔记(一) Spring概述

    博主Spring学习笔记整理大部分内容来自Spring实战(第四版)这本书.  强烈建议新手购入或者需要电子书的留言. 在学习Spring之前,我们要了解这么几个问题:什么是Spring?Spring ...

  5. Spring学习1-初识Spring

    一.简介   1.Spring是一个开源的控制反转(Inversion of Control ,IoC)和面向切面(AOP)的容器框架.它的主要目得是简化企业开发.  2.为何要使用Spring?   ...

  6. Spring学习,初识Spring

    Spring概述 将Spring理解为管理对象间依赖关系的容器 “解耦” 根据功能的不同,可以将一个系统中的代码分为 主业务逻辑 与 系统级业务逻辑 两类 ```Spring 是为了解决企业级开发的复 ...

  7. Spring学习 6- Spring MVC (Spring MVC原理及配置详解)

    百度的面试官问:Web容器,Servlet容器,SpringMVC容器的区别: 我还写了个文章,说明web容器与servlet容器的联系,参考:servlet单实例多线程模式 这个文章有web容器与s ...

  8. 1.1(Spring学习笔记)Spring基础(BeanFactory、ApplicationContext 、依赖注入)

    1.准备工作 下载Spring:http://repo.spring.io/libs-release-local/org/springframework/spring/    选择需要下载的版本    ...

  9. Java架构师之路 Spring学习笔记(一) Spring介绍

    前言 这是一篇原创的Spring学习笔记.主要记录我学习Spring4.0的过程.本人有四年的Java Web开发经验,最近在面试中遇到面试官总会问一些简单但我不会的Java问题,让我觉得有必要重新审 ...

  10. Spring学习(五)--构建Spring Web应用程序

    一.Spring MVC起步 看过猫和老鼠的小伙伴都可以想象Tom猫所制作的捕鼠器:它的目标 是发送一个小钢球,让它经过一系列稀奇古怪的装置,最后触发捕鼠 器.小钢球穿过各种复杂的配件,从一个斜坡上滚 ...

随机推荐

  1. 7-07. PAT排名汇总(25) (结构体 ZJU_PAT)

    题目链接:http://www.patest.cn/contests/ds/7-07 编程能力測试(Programming Ability Test,简称PAT)是浙江大学计算机科学与技术学院主办的专 ...

  2. 静态时序分析SAT

    1.   背景 静态时序分析的前提就是设计者先提出要求,然后时序分析工具才会根据特定的时序模型进行分析,给出正确是时序报告. 进行静态时序分析,主要目的就是为了提高系统工作主频以及增加系统的稳定性.对 ...

  3. .Net 路由处理厉害了

    通过设置路由,可以灵活的显示地址内容.它会自动转换为想要的控制器和方法中去. using System; using System.Collections.Generic; using System. ...

  4. JavaWeb简单介绍

    服务器端编程 技术种类 Servlet JSP Struts Spring Hibernate EJB Web Service Web服务器 IIS Apache Tomcat (提供对JSP和Ser ...

  5. 通过视频展示如何通过Samba配置PDC

    通过视频展示如何通过Samba配置PDC(Linux企业应用案例精解补充视频内容) 本文通过视频,真实地再现了在Linux平台下如何通过配置smb.conf文件而实现Samba Server模拟win ...

  6. Vijos——T1626 爱在心中

    https://vijos.org/p/1626 描述 “每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动.爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our H ...

  7. IOS基础学习日志(七)利用dispatch_once创建单例及使用

    自苹果引入了Grand Central Dispatch (GCD)(Mac OS 10.6和iOS4.0)后,创建单例又有了新的方法,那就是使用dispatch_once函数,当然,随着演进的进行. ...

  8. adb logcat 使用

    之前打印log的时候,使用的是别人配置好的快捷键,结果现在快捷键没有配置,具体的log命令就不会了.今天上网查了一下,记录下来 打印的log是 android.util.Log.e("zha ...

  9. 浏览器加载跟渲染html的顺序-css渲染效率的探究

    1.浏览器加载和渲染html的顺序1.IE下载的顺序是从上到下,渲染的顺序也是从上到下,下载和渲染是同时进行的.2.在渲染到页面的某一部分时,其上面的所有部分都已经下载完成(并不是说所有相关联的元素都 ...

  10. js函数的解析与执行过程

    function f(a,b,c){ alert(a);//函数字符串 alert(b); var b = 5; function a(){ } } f(1,2); //预处理 lexicalEnvi ...