精华内容
下载资源
问答
  • 容器是用来存放什么类型对象
    千次阅读
    2020-10-12 14:41:21

          趁着金九跳槽季,跳槽成功了。从之前的老东家跳入很老的大厂,也算完成了自己的大场梦。按照自己迂腐思想,两三年内应该不会跳槽了。所以希望静下心来搞搞基础,而不再是各种面试突击了。面试突击虽好,但总感觉根基不稳,有些问题面试不问,但在心中却存在疑问。存在未知,便有恐惧,所以想建立专栏,每天花一局王者的时间,夯实基础。当知识串起来之日,面试还会难吗,工资还能不涨吗。

    今日疑问点:Spring是容器,到底容的是什么。容器又在哪。

           刚工作之初读过Spring源码,因能力有限根本没有理解多少,仅一些皮毛。不懂底层原理,不懂设计模式,只看源码的Java书写,但确实也学到了很多很多东西。Spring的魅力可见一斑。这个专题是自己边学习边总结, 希望和大家一起进步,错误或者不足之处,还望指出。

    文章尽量简单,不涉及很细节的源码解析,只想把Spring的世界观建立起来,Spring源码很多,没有思路的看源码,效果也不会很好,先把主体框架弄明白,再抠细节。

    废话不多说,进入今日主题。

    1 Spring是容器,用来管理bean的容器,那么容得肯定是bean。bean简单说和对象非常类似。那么可以理解为spring就是帮我们管理对象,让我们使用的时候,可以直接获取对象,而不需要去new 一个了,就会省去我们自己new 对象的对属性的set的麻烦操作。(这只是最直观的好处。)。bean从我们使用者角度来看可以分为两种: 一 Spring启动后已经生成的可以直接用的,二 启动的时候不生成,用的时候才去生成的(专业术语叫做懒加载)。

    Spring作为一个框架,有万千代码类,这些代码有的是辅助功能,有的是工具功能,那么容器的类在哪?就是BeanFactory类,其内部定义了作为容器需要提供的功能方法。

    工作中常用的是DefaultListableBeanFactory

    查看类图(IDEA右键类名-->Diagrams -->show Diagram )

    可以看到该类是继承了 DefaultSingletonBeanRegistry

    下面进行说明。

    • DefaultSingletonBeanRegistry:存放具体的bean
      • singletonObjects: 存放bean的名称及实例
      • singletonFactories: 存放bean的名称及实例创建工厂
    public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    
    	/**
    	 * Internal marker for a null singleton object:
    	 * used as marker value for concurrent Maps (which don't support null values).
    	 */
    	protected static final Object NULL_OBJECT = new Object();
    
    
    	/** Logger available to subclasses */
    	protected final Log logger = LogFactory.getLog(getClass());
    
    	/** Cache of singleton objects: bean name --> bean instance */
    	// 生成的bean的名称和实例,Spring中会依靠这个beaName进行查找bean
    	private final Map<String, Object> 'singletonObjects' = new ConcurrentHashMap<String, Object>(64);
    
    	/** Cache of singleton factories: bean name --> ObjectFactory */
    	// bean名称和产生的工厂
    	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
    
    	/** Cache of early singleton objects: bean name --> bean instance */
    //省略本次不涉及得到的代码。.......
    }

    可以看到代码中的singletonObjects就是存放单例bean的容器,就是一个ConcurrentHashMap。暂且不管Spring是怎么把XML配置bean配置文件还是@bean相关的注解怎么转换成bean的。反正最终生成的单例bean是被存放到这个map中了,之后的获取也不管多复杂,多少场景,最后也肯定会是从map中获取bean。

    接下来在看DefaultListableBeanFactory

    在生成bean之前,Spring会先将我们定义的bean的信息保存起来,有些bean可能会暂时用不到就设置成懒加载的,先把定义存起来,用的时候直接生成比较快。而且bean的生成流程(各种大牛和面试官称其为bean的生命周期)非常复杂,先保存bean的信息,便于后期进行各种处理,比如 依赖注入,循环依赖等等过程。也就是我们写的@component ,@bean等注解的类,首先会被定义成Spring中的bean类的抽象 也就是BeanDefinition

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by FernFlower decompiler)
    //
    
    package org.springframework.beans.factory.config;
    
    import org.springframework.beans.BeanMetadataElement;
    import org.springframework.beans.MutablePropertyValues;
    import org.springframework.core.AttributeAccessor;
    import org.springframework.lang.Nullable;
    
    public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
        String SCOPE_SINGLETON = "singleton";
        String SCOPE_PROTOTYPE = "prototype";
        int ROLE_APPLICATION = 0;
        int ROLE_SUPPORT = 1;
        int ROLE_INFRASTRUCTURE = 2;
    
        void setParentName(@Nullable String var1);
    
        @Nullable
        String getParentName();
    
        void setBeanClassName(@Nullable String var1);
    
        @Nullable
        String getBeanClassName();
    
        void setScope(@Nullable String var1);
    
        @Nullable
        String getScope();
    
        void setLazyInit(boolean var1);
    
        boolean isLazyInit();
    
        void setDependsOn(@Nullable String... var1);
    
        @Nullable
        String[] getDependsOn();
    
        void setAutowireCandidate(boolean var1);
    
        boolean isAutowireCandidate();
    
        void setPrimary(boolean var1);
    
        boolean isPrimary();
    
        void setFactoryBeanName(@Nullable String var1);
    
        @Nullable
        String getFactoryBeanName();
    
        void setFactoryMethodName(@Nullable String var1);
    
        @Nullable
        String getFactoryMethodName();
    
        ConstructorArgumentValues getConstructorArgumentValues();
    
        default boolean hasConstructorArgumentValues() {
            return !this.getConstructorArgumentValues().isEmpty();
        }
    
        MutablePropertyValues getPropertyValues();
    
        default boolean hasPropertyValues() {
            return !this.getPropertyValues().isEmpty();
        }
    
        void setInitMethodName(@Nullable String var1);
    
        @Nullable
        String getInitMethodName();
    
        void setDestroyMethodName(@Nullable String var1);
    
        @Nullable
        String getDestroyMethodName();
    
        void setRole(int var1);
    
        int getRole();
    
        void setDescription(@Nullable String var1);
    
        @Nullable
        String getDescription();
    
        boolean isSingleton();
    
        boolean isPrototype();
    
        boolean isAbstract();
    
        @Nullable
        String getResourceDescription();
    
        @Nullable
        BeanDefinition getOriginatingBeanDefinition();
    }
    
    BeanDefinition是对Spring中bean的定义的抽象,假设我们不看上述代码自己考虑我们自己定义bean的定义信息,大体都需要什么信息,

    1 bean的class信息:生成一个对象的必须信息

    2 bean的作用域信息:在开发中有的对象用完就不想要了,下次会新建新的,有的是一个对象一直用。有的对象是一个请求一个。满足这个功能的话 ,作用域信息也是必不可少的。

    3 bean是否懒加载信息:

    4 bean的初始化问题:有的对象是直接构造函数new的,有的却是工厂方法生成的,如果是工厂方法生成的话,这个时候是不是就需要把生成对象的方法保存起来呢,告诉Spring生成方法。

    当然这只是我能想到的,Spring能想到的肯定更多,适应更多的场景。

    总而言之,Spring会将需要生成bean的类进行扫描,然后生成这个bean定义信息,保存起来。

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by FernFlower decompiler)
    //
    
    package org.springframework.beans.factory.support;
    
    //省略import信息
    
    public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
        @Nullable
        private static Class<?> javaxInjectProviderClass;
        private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories;
        @Nullable
        private String serializationId;
        private boolean allowBeanDefinitionOverriding = true;
        private boolean allowEagerClassLoading = true;
        @Nullable
        private Comparator<Object> dependencyComparator;
        private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();
        private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap(16);
        //这个map就是用来存储bean定义的map。
        private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);
        private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap(64);
        private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap(64);
        private volatile List<String> beanDefinitionNames = new ArrayList(256);
        private volatile Set<String> manualSingletonNames = new LinkedHashSet(16);
        @Nullable
        private volatile String[] frozenBeanDefinitionNames;
        private volatile boolean configurationFrozen = false;
    
        //省略方法。
    }

    可以看到类中的beanDefinitionMap就是用来存储bean的定义信息的map。

     

    总结: 两个ConcurrentHashMap构成了Spring的容器。(简单才能记住)

    更多相关内容
  • ——存放各种类型数据的容器,包括变量、常量和信号  1. 变量(VARIABLE)  规则:只能在进程(PROCESS)、函数(FUNCTION)和过程(PROCEDURE)中说明和使用的局域量  定义格式:  VARIABLE 变量名:数据...
  • Java容器详解

    2021-02-24 10:20:29
    1.什么是容器在Java当中,有一个类专门用来存放其它类的对象,这个类就叫做容器,它就是将若干性质相同或相近的类对象组合在一起而形成的一个整体。2.常用的Java1.List有序的collection(也称为序列)。此接口的用户...
  • 深入理解Java中的容器

    2021-02-24 10:21:56
    如果有一个类专门用来存放其它类的对象,这个类就叫做容器,或者就叫做集合,集合就是将若干性质相同或相近的类对象组合在一起而形成的一个整体之所以需要容器:1、数组的长度难以扩充2、数组中数据的类型必须相同...
  • Abaqus对象类型

    千次阅读 2019-06-27 09:44:21
    容器:是包含相同类型对象对象。在Abaqus中容器可以是仓库(repository)或者序列(sequence)。例如,一个仓库的steps容器中就包含着分析中的所有step,我们可以通过steps容器来访问一个step...

    通常abaqus将对象模型分为Session、Mdb和Odb对象。

    对象模型中的对象既可以是容器(Container),也可以是单个对象(Singular object)

    容器:是包含相同类型对象的对象。在Abaqus中容器可以是仓库(repository )或者序列(sequence)。例如,一个仓库的steps容器中就包含着分析中的所有step,我们可以通过steps容器来访问一个step。

    单个对象:不属于容器的对象属于单个对象,仅包含一个该类型的对象,例如Session和Mdb对象。

     

     from abaqus import *:导入Session对象和Mdb对象

    from odbAccess import *:允许访问脚本产生Abaqus输出结果。

     

    Session对象:存在于一次Abaqus会话中,它并不能保存到CAE文件或者ODB文件。Session对象并没有对应的构造函数,用户不能从脚本中创建一个Session对象。当用户开启一个新的Abaqus窗口就称为打开了一个新的会话,它会建立一套新的会话对象。

    Mdb对象:from abaqus import *:创建名称为mdb的Mdb对象。用来存放有限元模型,Mdb对象能存放于模型数据库中,可以在Abaqus/CAE会话中被覆盖。包括Model对象和Job对象。Model对象又由Part对象、Section对象、Material对象和Step对象等。

    Odb对象:该对象保存在输出数据库中,包含模型和结果数据:

    在大多数Abaqus脚本接口的命令中都以一下之一开头:Session,Mdb或者Odb对象,例如:

    from abaqus import *

    from abaqusConstants import *

    session.Viewport(name='Viewport: 1', origin=(0.0, 0.0), width=406.905181884766,

    height=244.475006103516)

    session.viewports['Viewport: 1'].makeCurrent()

    session.viewports['Viewport: 1'].maximize()

     

     

    对象数据通过Abaqus自身所提供的setValues()来修改。

     

     

    参考:

    http://ivt-abaqusdoc.ivt.ntnu.no:2080/v6.14/books/cmd/default.htm

    展开全文
  • 一、服务器和容器 1. Web服务器 2. Web容器 ① Web容器的组成 ② Web容器的作用 3. Servlet容器 ① Servlet容器的作用 ② Servlet容器的工作过程 ③ Servlet ④ Servlet的工作过程 ⑤ Servlet变化过程 4. Spring容器...


    一、服务器和容器

    1. Web服务器

    广义的Web服务器(Web Server):提供web服务的软件或主机,即Web服务器软件或装有Web服务器软件的计算机。

    Web服务器可以处理 HTTP 协议,响应针对静态页面或图片的请求(静态请求),进行页面跳转。

    有的Web服务器还能处理动态请求,它会把动态请求委托其它程序(它的扩展、某种语言的解释引擎(php)、Web容器)。

    常见的Web服务器有:Apache、IIS、Tomcat、Jetty、JBoss、webLogic等。

    2. Web容器

    Web容器是一种服务程序,在服务器一个端口就有一个提供相应服务的程序,这个程序就是用来处理从客户端发出的请求的。一个服务器可以有多个容器。

    常见的Web容器有:IIS(asp容器)、Tomcat(servlet容器)、Jboss(EJB容器)。

    其实现在在很多时候,大家对Web服务器和Web容器已经没有了明确的界限。通常把Web服务器和Web容器当成同一个东西在讲。

    文章后面部分所讲的web容器都是以Tomcat容器为例。

    ① Web容器的组成

    Web容器管理Servlet(通过Servlet容器)、监听器(Listener)、过滤器(Filter)等。

    • Servlet:称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,是一个Java类。它负责客户端和服务端的信息交互和处理。

      Servlet不能独立运行(没有main方法),必须存放在Servlet容器中,由Servlet容器去管理Servlet。

    • Filter:Servlet的作用是处理请求,而Filter的作用是拦截请求和放行,在拦截请求后可以修改request和response,实现我们想实现的功能。Filter不能产生一个请求或者响应,只是能对请求或者响应进行拦截。

    • Listener:监听器。它可以监听Application、Session、Request对象,当这些对象发生变化的时候就会调用对应的监听方法。

    ② Web容器的作用

    • 管理和布置Web应用
    • 响应针对静态页面或图片的请求(静态请求
    • 动态请求委托给其他程序(Servlet容器、CGI等等技术)

    ServletFilterListener这些都是在Web容器的掌控范围里。但不在Spring容器和SpringMVC容器的掌控范围里。所以无法在这些类中直接使用Spring注解的方式来自动装配需要的对象,因为Web容器是无法识别Spring注解的。

    Web容器没有Servlet容器,也是可以直接访问静态页面的,比如Apache服务器。但是如果要显示jsp/servlet,就必需要Servlet容器。可是光有Servlet容器也是不够的,因为它需要被解析成html输出,所以仍需要一个Web容器。

    大多数的Web容器都包含Servlet容器,如:Tomcat、Jetty、webLogic。

    3. Servlet容器

    Servlet容器全称server applet,意为服务程序。Servlet容器负责管理Servlet,用与处理动态请求。

    Servlet容器是与Servlet交互的Web服务器的一部分,它可以从Web页面接收请求后再将这些请求重定向到Servlet对象中,然后将动态生成的结果返回到正确的位置中。

    Servlet容器给上级容器(Tomcat)提供doGet()和doPost()等方法。其生命周期实例化、初始化、调用、销毁受控于Tomcat容器。

    利用Servlet容器提供的方法,能轻松的让Servlet与Web服务器对话,而不用自己建立serversocket、监听某个端口、创建流等等。容器知道自己与Web服务器之间的协议,不用担心Web服务器和你自己的Web代码之间的API,只需要考虑如何在Servlet中实现业务逻辑。

    大家通常把Tomcat称作Servlet容器,因为Tomcat就是一个围绕着Servlet工作的一个服务器软件。

    ServletContext与Servlet容器的关系

    ServletContext是Servlet与Servlet容器之间的直接通信的接口。

    Servlet容器在启动一个Web应用时,会为它创建一个ServletContext对象。每个web应用有唯一的ServletContext对象。
    同一个Web应用的所有Servlet对象共享一个ServletContext,Servlet对象可以通过它来访问容器中的各种资源。

    为了方便描述,后文直接将ServletContext称作Servlet容器。

    ① Servlet容器的作用

    • 管理Servlet(业务类)

      • 负责加载类、实例化和初始化Servlet
      • 调用Servlet的service方法提供服务
      • 管理Servlet实例的垃圾回收
      • 管理Servlet之间的共同资源(servletContext)
    • 处理动态请求

      • 解析包装请求
      • 调用某个Servlet
      • 将Servlet的执行结果返回给请求端
    • 多线程

      • 自动为它所接收的每个Servlet请求创建一个新的java线程
      • 但是也会出现线程安全问题
    • 实现简便安全

      • 使用xml部署描述文件来配置和修改安全性
    • JSP支持

      • 负责将jsp代码翻译为真正的java代码
    • 管理通信

      • 负责管理servlet与web服务器之间的通信

    ② Servlet容器的工作过程

    • Web服务器接收HTTP请求。
    • Web服务器将请求转发到Servlet容器。
    • 如果对应的Servlet不在容器中,那么将被动态检索并加载到容器的地址空间中。
    • 容器调用init()方法进行初始化(仅在第一次加载 Servlet 时调用一次)。
    • 容器调用Servlet的service()方法来处理HTTP请求,即读取请求中的数据并构建响应。Servlet将暂时保留在容器的地址空间中,可以继续处理其它 HTTP 请求。
    • Servlet容器将结果返回给Web服务器,Web服务器将动态生成的结果返回到浏览器/客户端。

    ③ Servlet

    Servlet是用来处理客户端请求并产生动态网页内容的Java类,Servlet主要是用来处理或者是存储HTML表单提交的数据,产生动态内容,在无状态的HTTP协议下管理状态信息。

    所有的Servlet都必须要实现的核心的接口是javax.servlet.Servlet。每一个Servlet都必须要直接或者是间接实现这个接口,或者是继承javax.servlet.GenericServlet或者javax.servlet.http.HTTPServlet。
    在这里插入图片描述

    ④ Servlet的工作过程

    • 客户端发送请求,请求传递到Servlet容器;
    • Servlet容器将数据转换成服务端可以处理的数据后发给服务端;
    • 当服务端处理完成之后,返回给Servlet容器;
    • Servlet容器将其转换成客户端可以处理的数据交给客户端。

    ⑤ Servlet变化过程

    • 不同请求的处理逻辑不同,于是将逻辑处理这块单独抽取出来成了Servlet
    • 但是Servlet并不擅长往浏览器输出HTML页面,所以出现了JSP
    • 随着三层架构的出现,一些逻辑从Servlet抽取出来,分担到Service和Dao
    • 随着Spring的出现,Servlet开始退居幕后,取而代之的是方便的SpringMVC。

    SpringMVC的核心组件DispatcherServlet其实本质就是一个Servlet。它在原来HttpServlet的基础上,又封装了一条逻辑。

    4. Spring容器

    Spring容器用来管理Service和Dao。

    5. SpringMVC容器

    SpringMVC容器用来管理Controller、视图解析器(view resolvers)等。

    6. SpringBoot容器

    SpringBoot容器是一个应用容器,管理所有bean。

    大家也常叫做Spring容器,这为了和上面的Spring容器区分开来,称他为SpringBoot容器。

    二、容器相关知识归纳

    1. 各种容器的管理范围

    • Web容器:管理Listener(监听器)、Filter(过滤器)、间接管理Servlet(通过Servlet容器)
    • Servlet容器:管理Servlet
    • Spring容器:管理Service、Dao
    • SpringMVC容器:管理Controller
    • SpringBoot容器:管理所有Bean

    2. 为何设计父子容器

    在早期的Spring+SpringMVC的项目中,会有父子容器这个概念(Spring容器:父容器;SpringMVC容器:子容器)。

    早期为什么会这样设计呢?

    • 早期Spring为了划分框架边界。将Service、Dao层交给Spring来管理(父容器)、Controller层交给SpringMVC管理(子容器)
    • Spring规定:子容器可以获取父容器的bean,但父容器不可以获取子容器的bean(父子容器的关系就像子类和父类的关系)

    可见,父子容器的设计主要是要是为了方便子容器的切换

    比如:我们想把Web层从SpringMVC替换成Struts, 那么只需要将spring­mvc.xml替换成Struts的配置文件struts.xml即可,而spring­core.xml不需要改变。

    因此才会有网络上大家常说的:Service、Dao无法注入Controller,Controller却可以注入Service、Dao。

    但需注意:这概念只在Spring+SpringMVC项目中,SpringBoot项目并没有父子容器这个概念。

    3. 父子容器的事务问题

    事务管理器属于Spring容器管理,SpringMVC容器无法访问到事务相关的对象,所以不能在Controller上配置事务。

    三、各种项目中的容器

    1. SpringMVC项目

    ① 项目背景

    • SpringMVC+Tomcat
    • 配置DispatcherServlet的为dispatcherServlet。

    项目用到的容器:Web容器、Servlet容器、SpringMVC容器。

    ② Servlet容器

    全局上下文servletContext(Servlet容器)是一个ApplicationContextFacade类型的对象。

    Servlet容器的属性:

        private final Map<String, Class<?>[]> classCache;
        private final Map<String, Method> objectCache;
        private final ApplicationContext context;
    

    servletContext中context属性就是Tomcat的上下文信息。它是一个ApplicationContext类型的对象。

    context中有一个Map类型的属性attributes,我们的SpringMVC容器就在里面。

    ③ SpringMVC容器

    SpringMVC容器是一个XmlWebApplicationContext类型的对象。

    attributes中键为org.springframework.web.servlet.FrameworkServlet.CONTEXT.dispatcherServlet的值存的就是SpringMVC容器对象。

    SpringMVC容器的主要属性:

    • servletContext:Servlet容器的引用
    • servletConfig:servletConfig的引用
    • beanFactory:DefaultListableBeanFactory类型,管理SpringMVC容器中的所有bean
    • configLocations:SpringMVC的配置文件路径,如classpath:springMVC.xml
    • parent:父容器,值为null

    ④ 容器关系图

    在这里插入图片描述

    2. Spring+SpringMVC项目

    ① 项目背景

    • Spring+SpringMVC+Mybatis+Tomcat
    • 配置DispatcherServlet的为dispatcherServlet。

    项目用到的容器:Web容器、Servlet容器、Spring容器、SpringMVC容器。

    ② Servlet容器

    全局上下文servletContext(Servlet容器)是一个ApplicationContextFacade类型的对象。

    Servlet容器的属性:

        private final Map<String, Class<?>[]> classCache;
        private final Map<String, Method> objectCache;
        private final ApplicationContext context;
    

    servletContext中context属性就是Tomcat的上下文信息。它是一个ApplicationContext类型的对象。

    context中有一个Map类型的属性attributes,我们的Spring容器和SpringMVC容器都在里面。

    ③ Spring容器

    Spring容器是一个XmlWebApplicationContext类型的对象。

    attributes中键为org.springframework.web.context.WebApplicationContext.ROOT的值存的就是Spring容器对象。

    Spring容器主要属性:

    • servletContext:Servlet容器的引用
    • beanFactory:DefaultListableBeanFactory类型,管理Spring容器中的所有bean
    • parent:父容器,这里Spring容器就是父容器,所以值为null

    ④ SpringMVC容器

    SpringMVC容器是一个XmlWebApplicationContext类型的对象。

    attributes中键为org.springframework.web.servlet.FrameworkServlet.CONTEXT.dispatcherServlet的值存的就是SpringMVC容器对象。

    SpringMVC容器主要属性:

    • servletContext:servletContext的引用
    • servletConfig:servletConfig的引用
    • beanFactory:DefaultListableBeanFactory类型,管理Spring容器中的所有bean
    • configLocations:SpringMVC的配置文件路径,如classpath:springMVC.xml
    • parent:父容器,也就是Spring容器

    ⑤ 父子容器

    在Spring+SpringMVC项目中,Spring容器和SpringMVC容器为父子容器:

    • Spring容器和SpringMVC容器共同管理所有的bean
    • Spring容器管理Service和Dao,SpringMVC容器管理Controller
    • Spring容器为父容器,SpringMVC容器为子容器
    • SpringMVC容器有指向Spring容器的引用,但Spring容器没有指向SpringMVC容器的引用

    所以Controller可以注入Service和Dao对象,但是在Service和Dao里不可以注入Controller对象。

    SpringMVC的拦截器(Interceptor)也是SpringMVC容器管理的,所以Interceptor也是可以可以注入Service和Dao对象的。

    ⑥ 容器创建过程

    容器的创建过程:

    1. Tomcat服务器启动,Servlet容器启动
    2. 创建Spring容器的实例
    3. 创建SpringMVC容器的实例

    容器的详细创建过程可参考文章:Spring+SpringMVC项目中的容器初始化过程

    ⑦ 容器关系图

    在这里插入图片描述

    3. SpringBoot项目

    ① 项目背景

    SpringBoot+内置Tomcat

    SpringBoot项目中的容器:Web容器、Servlet容器、SpringBoot容器。

    对于SpringBoot项目中的容器,大家也常叫做Spring容器,这为了和上面的Spring容器区分开来,称他为SpringBoot容器。

    ② Servlet容器

    全局上下文servletContext(Servlet容器)是一个ApplicationContextFacade类型的对象。

    servletContext对象有三个属性:

        private final Map<String, Class<?>[]> classCache;
        private final Map<String, Method> objectCache;
        private final ApplicationContext context;
    

    servletContext中context属性就是Tomcat的上下文信息。它是一个ApplicationContext类型的对象。

    context中有一个Map类型的属性attributes,我们的SpringBoot容器就在里面。

    ③ SpringBoot容器

    SpringBoot容器是一个AnnotationConfigServletWebServerApplicationContext类型的对象。

    attributes中键为org.springframework.web.context.WebApplicationContext.ROOT的值存的就是SpringBoot容器对象。

    attributes中键为org.springframework.web.servlet.FrameworkServlet.CONTEXT.dispatcherServlet的值存的也是SpringBoot容器对象。

    SpringBoot容器主要属性:

    • servletContext:servletContext的引用
    • beanFactory:DefaultListableBeanFactory类型,管理SpringBoot容器中的所有bean
    • parent:null

    ④ 容器创建过程

    容器的详细创建过程可参考文章:SpringBoot项目中的容器初始化过程

    ⑤ 容器关系图

    在这里插入图片描述

    展开全文
  • c++中我相信大家经常要用到STL里面的各种容器存放自己的数据,既然我们用的这么频繁那么就相应该有一些疑问?

    ~~~~我的生活,我的点点滴滴!!                  

                c++中我相信大家经常要用到STL里面的各种容器来存放自己的数据,既然我们用的这么频繁那么就相应该有一些疑问?

     1.容器里面什么时候应该存指针?
     2.容器里面什么时候应该存对象?
     3.容器怎么在遍历的时候删除某元素?
     4.容器应该怎么释放掉?


     一.分析一下STL里面工作方式
                  对于内建类型(int float char等),容器的工作方式是纯粹的位拷贝,这里没有什么需要多说的。
    对于自定义的对象,容器容纳了对象(比如通过insert或push_back等),但容器中存放的对象不是你给它们的那个对象,因为两个对象在内存中的位置不一样。此外,当你从容器中获取一个对象时,你所得到的对象不是容器里的那个对象。取而代之的是,当你向容器中添加一个对象(比如通过insert或push_back等),进入容器的是你指定的对象的拷贝。拷进去,拷出来。拷贝是STL的方式。可以通过自己写一个例子打印出地址来看。


    二.存放对象的情况
                 明白了容器的工作方式,那么进一步来讨论容器存放对象和指针在操作过程中的开销。内建类型的数据进行拷贝的方式是位拷贝,自定义类型的数据进行拷贝会调用类的拷贝构造函数,这个函数是每个类都有的,如果类中没有显式的声明那么编译器也会给提供一个默认的拷贝构造函数。如果一个类的数据非常多,或者包含其他复杂自定义类型,那么此时类的拷贝构造的开销是非常大的。
    此时容器中要是存放的是对象vector,那么一个简单的插入操作的代价也是惊人的,更别说什么排序之类的操作,很容易带来性能上的瓶颈,这个时候就需要在容器中存放对象的指针vector,这样的话就避免了这些多余的拷贝消耗,因为指针就是一个机器字长,拷贝的代价可以忽略不计。

    typedef std::vector ObjectVector;
    
    typedef std::vector PointerVector;
    
    //下面是存贮对象的情况
    
    begin = GetTickCount();
    
    ObjectVector objectVector;
    
    for (int i = 0; i < MAX; i++)
    {
    
    <span style="white-space:pre">	</span>objectVector.push_back(*pCom);
    
    }
    
    end = GetTickCount();
    
    cout << "存放对象消耗的时间:";
    
    cout << end - begin << "毫秒 ";
    
    
    
    //下面是存贮指针的情况
    
    begin = GetTickCount();
    
    PointerVector pinterVector;
    
    for (int i = 0; i < MAX; i++)
    
    {
    
    	pinterVector.push_back(pCom);
    
    }
    
    end = GetTickCount();
    
    cout << "存放指针消耗的时间:";
    
    cout << end - begin << "毫秒 ";

    下面的结果是在Release版本下,并且编译器的优化关闭的情况下,这和我们目前的客户端设置一样:

    MAX = 4000


    MAX = 40000


    MAX = 400000


    上面的数据没有用统计学的方法去测试,只是取了一次结果,我测试了多次结果在数量级上是一样的(用上面的数据只是说明拷贝的代价是巨大的,并没有强调必须用指针)。
                   分析完了拷贝的性能消耗,再看看另一个问题,就是声明了一个存放基类对象的容器,如果此时向容器中插入子类的对象,那么子类特有的那些内容就会被无情剥离(slicing)。这是一个很严重的问题。解决的方法还是使用基于指针的容器。


    三.存放指针的情况

                   上面提到的两个问题用指针确实比用对象好,问题不是这么绝对。在上面考虑拷贝消耗的时候有个前提:如果一个类的数据非常多,或者包含其他复杂自定义类型,并且需要大量的使用需要容器内部对象拷贝的操作。如果一个对象中就是几个简单的内建类型,或者干脆就是一个简单的内建类型的数据,那么再用指针可真是得不偿失了,因为使用指针需要程序员去管理内存。完全没有必要为了节省几个int类型的拷贝消耗而去自己去做内存的管理,确实完全没有必要。用指针就需要自己手动的去管理这些指针所指向的内存,stl容器确实可以动态申请内存使自己变大以容纳更多的元素,但这些动态空间存放的是你的指针,而并不是你指针指向的动态内存,你的指针内存当然需要你去管理,如果实在不想做这些管理工作,可以去使用智能指针。


    四.总结一下存指针与对象

    1.stl容器可以存放内建类型、自定义类型、指针类型的元素。

    2.元素如果是内置数据类型,那么就存放数据本身。

    3.元素如果是复杂类型,并且在使用容器的过程中需要容器的元素进行大量的拷贝操作的时候,就要考虑在容器中放入指针;

    4.存放指针容易出现内存的泄露,所以在使用的时候需要考虑清楚,如能接口设计的合理,能保证容器在使用的过程中不进行大量的拷贝工作,在容器中存放对象是最好的了。

    5.使用智能指针是一种两种优点都兼备的,既有指针的操作效率,又避免了自己手动管理内存带来的问题。

    6.指针可以解决派生类对象存放在使用基类实例化的容器中的剥离(slicing)问题。
    在考虑容器中是存放对象还是指针的时候脑子里时刻要想到,我的操作需要容器做多少拷贝工作,这些拷贝操作带来的损耗能否接受,从这个本质问题上把握好了,选择起来就不是问题了,要根据实际情况灵活运用。


    五. STL遍历过程中删除元素

    如果想在容器遍历过程中删除里面某个值时,用迭代器(这是最简单的方法),看下面代码:

    std::list< int> List;
    std::list< int>::iterator itList;
    for( itList = List.begin(); itList != List.end(); )
    {
    if( WillDelete( *itList) )
    {
       itList = List.erase( itList);
    }
    else
      itList++;
    }
    或者:
    std::list< int>::iterator itList;
    for( itList = List.begin(); itList != List.end(); )
    {
    if( WillDelete( *itList) )
    {
       List.erase( itList++);
    }
    else
       itList++;
    }

    重点是当删除后就要往后移一位,不然下次遍历到那时,已经不存在,就会报错的。


    六. STL中删除元素释放问题

                   STL中不管是erase或remove都不会释放对象的内存空间,他只是释放了STL里面用来存放这个对象或指针的空间,所以依然需要自己去手动释放,并且释放是有先后顺序的,要先delete 在调用STL里容器对应的erase函数。

    list<obj *>m_list;
    list<obj *>::iterator ite;
    for( ite = m_list.begin(); ite != m_list.end(); ++ite)
    {
    	delete (*ite);
    	ite = m_list.erase(ite);
    }
    
    总之一条原则, 你 new 的, 你去 delete 释放。不是你 new 的, 就不该你去释放。你往 list 里面插入元素时所需的内存是 list 自己申请的, 那它就会自己释放。但是你存在里面的对象不是他的,他不会管!



    展开全文
  • 阿里面试真题:Spring容器启动流程

    万次阅读 多人点赞 2020-11-30 11:39:04
    org.springframework.context.annotation.AnnotatedBeanDefinitionReader#doRegisterBean 这个步骤主要是用来解析用户传入的 Spring 配置类,其实也是解析成一个 BeanDefinition 然后注册到容器中,没有什么好说的...
  • Java容器可以说是增强程序员编程能力的基本工具,本系列将带您深入理解容器类。 容器的用途 如果对象的数量与生命周期都是固定的,自然我们也就不需要很复杂的数据结构。 我们可以通过创建引用来持有对象,如 ...
  • BLOB (binary large object),二进制大对象,是一个可以存储二进制文件的容器。 在计算机中,BLOB常常是数据库中用来存储 二进制文件的字段类型。 BLOB是一个大文件,典型的BLOB是一张图片或一个声音文件,由于它们...
  • JAVA中的对象容器

    千次阅读 2018-09-18 18:18:35
    容器的用途 如果对象的数量与生命周期都是固定的,自然我们也就不需要很复杂的数据结构。 我们可以通过创建引用来持有对象,如 Class clazz; 也可以通过数组来持有多个对象,如 Class[] clazs = new Class[10...
  • Python中容器指的是什么

    千次阅读 多人点赞 2019-06-30 23:06:17
    容器容器是一种把多个元素...容器仅仅只是用来存放数据的,我们平常看到的 l = [1,2,3,4]等等,好像我们可以直接从列表这个容器中取出元素,但事实上容器并不提供这种能力,而是可迭代对象赋予了容器这种能力。 ...
  • 它的主要目的之一就是用来指定容器要持有什么类型对象 泛型只能只能代表引用类型,不能是原始类型,原始类型有byte/short/int/long 浮点型:float.double 字符型char 布尔型:boolean,引用类型与原始类型的区别...
  • 同步类容器和并发类容器

    万次阅读 多人点赞 2019-07-31 19:22:20
    什么会出现同步容器? 在Java的集合容器框架中,主要有四大类别:List、Set、Queue、Map。 注意Collection和Map是顶层接口,而List、Set、Queue接口则分别继承了Collection接口,分别代表数组、集合和队列这三大...
  • 并发容器之ThreadLocal详解

    千次阅读 多人点赞 2019-10-11 19:12:30
    ThreadLocalMap是threadLocal一个静态内部类,和大多数容器一样内部维护了一个数组,同样的threadLocalMap内部维护了一个Entry类型的table数组。 /** * The table, resized as necessary. * table.length MUST ...
  • blob是什么类型

    千次阅读 2021-04-13 15:33:39
     在计算机中,BLOB常常是数据库中用来存储二进制文件的字段类型。    BLOB是一个大文件,典型的BLOB是一张图片或一个声音文件,由于它们的尺寸,必须使用特殊的方式来处理(例如:上传、下载或者存放到一个数据库...
  • 数据库中的blob是什么类型

    千次阅读 2020-09-02 14:14:00
     在计算机中,BLOB常常是数据库中用来存储二进制文件的字段类型。  BLOB是一个大文件,典型的BLOB是一张图片或一个声音文件,由于它们的尺寸,必须使用特殊的方式来处理(例如:上传、下载或者存放到一个数据库)...
  • Java中数组可以存储对象吗?

    千次阅读 2021-02-13 02:15:38
    数组是一个容器,可以存放固定数量的项目,这些项目应该是相同的类型。大多数数据结构使用数组来实现它们的算法。以下是理解数组概念的重要术语。元素:存储在数组中的每个项目都称为元素。索引:数组中元素的每个...
  • C++序列容器存储智能指针详解

    千次阅读 2019-09-14 10:13:45
    存放元素基类指针的容器也可以保存其派生类型的指针。当要处理有共同基类的任意对象序 列时,这种功能是非常有用的。应用这一特性的一个常见示例是展示一个含有直线、曲线和几何形状的对象序列。 对指针容器...
  • 一篇文章帮你玩转vector容器(C++)

    千次阅读 多人点赞 2021-11-12 00:07:40
    目录1.vector容器概述2.vector容器存放内置数据类型3.vector容器存放自定义数据类型4....而迭代器能够用来遍历容器对象 2.vector容器存放内置数据类型 #include<iostream> using namespace std;
  • BLOB是一种什么类型

    千次阅读 2020-05-06 09:08:23
    BLOB (binary large object)----二进制大对象,是一个可以存储二进制文件的容器。  在计算机中,BLOB常常是数据库中用来存储二进制文件的字段类型。  BLOB是一个大文件,典型的BLOB是一张图片或一个声音文件,由于...
  • CAN笔记(20) 过程数据对象

    万次阅读 2019-09-11 11:48:25
    过程数据对象、CAN-ID定义、传输形式、通信参数、映射参数
  • 第六章 Java容器

    千次阅读 2019-09-10 21:05:00
    如果两个对象相同,那么他们的hashcode应该相等 如果两个对象不相同,他们的hashcode可能相同 Queue (Interface) Queue用户模拟队列这种数据结构,队列通常是指“先进先出”(FIFO,first-in-first-out)的容器。...
  • 首先STL容器中最好是不要存放指针,如果外部被new出来的对象被销毁了,那么存放容器中的指针就变成空指针了,这样在遍历的时候,就爆炸了。但是在STL容器存放指针也有他的好处。首先是在容器中放入对象:#...
  • 作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客 本文网址: 目录 前言: 第1章 Docker概述 1.1 Docker的详解教程 ...1.2 Docker容器概述 ...1.3 哪些人适合了解...3.2 容器...
  • c++容器用法

    千次阅读 2021-07-12 11:10:24
    因为vector 容纳着 其他对象,所以它也常被称为容器container。 要想使用 vector,必须包含适当的头文件。需要做如下的声明 #include <vector> using std::vector; 注意:vector是模板而非类型,由vector...
  • 文章目录C++中常用的std标准容器顺序容器:有序关联容器:无序关联容器:顺序容器1. vector容器a. vector的定义与初始化b. vecotr常使用的操作c. 小结:2. string容器a. string的初始化b. string中包含的专有的操作...
  • 容器是Spring的核心,用来存放、初始化、管理Bean对象的(通过IOC管理)、相当于生产Bean的工厂。在xml中进行配置。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 121,358
精华内容 48,543
热门标签
关键字:

容器是用来存放什么类型对象