springboot 시작 해석 8

26413 단어
이 장에서 런 방법의 15행 코드를 계속 분석한다.
public ConfigurableApplicationContext run(String... args) {
        1.StopWatch stopWatch = new StopWatch();
        2.stopWatch.start();
        3.ConfigurableApplicationContext context = null;
        4.Collection exceptionReporters = new ArrayList<>();
        5.configureHeadlessProperty();
        6.SpringApplicationRunListeners listeners = getRunListeners(args);
        7.listeners.starting();
        try {
        8.  ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                    args);
        9.  ConfigurableEnvironment environment = prepareEnvironment(listeners,
                    applicationArguments);
        10. configureIgnoreBeanInfo(environment);
        11. Banner printedBanner = printBanner(environment);
        12. context = createApplicationContext();
        13. exceptionReporters = getSpringFactoriesInstances(
                SpringBootExceptionReporter.class,
                    new Class[] { ConfigurableApplicationContext.class }, context);
        14.     prepareContext(context, environment, listeners, applicationArguments,
                    printedBanner);
        15. refreshContext(context);
        16. afterRefresh(context, applicationArguments);
        17. stopWatch.stop();
        18. if (this.logStartupInfo) {
        19.     new StartupInfoLogger(this.mainApplicationClass)
                        .logStarted(getApplicationLog(), stopWatch);
            }
        20. listeners.started(context);
        21. callRunners(context, applicationArguments);
        }
        catch (Throwable ex) {
        22. handleRunFailure(context, ex, exceptionReporters, listeners);
            throw new IllegalStateException(ex);
        }

        try {
        23. listeners.running(context);
        }
        catch (Throwable ex) {
        24. handleRunFailure(context, ex, exceptionReporters, null);
            throw new IllegalStateException(ex);
        }
        return context;
    }
  • 그 중에서 15번째 줄의 코드는 다음과 같다:
  •     @Override
        public void refresh() throws BeansException, IllegalStateException {
            synchronized (this.startupShutdownMonitor) {
                // Prepare this context for refreshing.
                prepareRefresh();
    
                // Tell the subclass to refresh the internal bean factory.
                ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
                // Prepare the bean factory for use in this context.
                prepareBeanFactory(beanFactory);
    
                try {
                    // Allows post-processing of the bean factory in context subclasses.
                    postProcessBeanFactory(beanFactory);
    
                    // Invoke factory processors registered as beans in the context.
                    invokeBeanFactoryPostProcessors(beanFactory);
    
                    // Register bean processors that intercept bean creation.
                    registerBeanPostProcessors(beanFactory);
    
                    // Initialize message source for this context.
                    initMessageSource();
    
                    // Initialize event multicaster for this context.
                    initApplicationEventMulticaster();
    
                    // Initialize other special beans in specific context subclasses.
                    onRefresh();
    
                    // Check for listener beans and register them.
                    registerListeners();
    
                    // Instantiate all remaining (non-lazy-init) singletons.
                    finishBeanFactoryInitialization(beanFactory);
    
                    // Last step: publish corresponding event.
                    finishRefresh();
                }
    
                catch (BeansException ex) {
                    if (logger.isWarnEnabled()) {
                        logger.warn("Exception encountered during context initialization - " +
                                "cancelling refresh attempt: " + ex);
                    }
    
                    // Destroy already created singletons to avoid dangling resources.
                    destroyBeans();
    
                    // Reset 'active' flag.
                    cancelRefresh(ex);
    
                    // Propagate exception to caller.
                    throw ex;
                }
    
                finally {
                    // Reset common introspection caches in Spring's core, since we
                    // might not ever need metadata for singleton beans anymore...
                    resetCommonCaches();
                }
            }
        }
    
    

    본 장은 주로 register Bean Post Processors, init Message Source, init Application Event Multicaster, on Refresh,register Listeners,finish Bean Factory Initialization,finish Refresh,destroy Beans,cancel Refresh,reset Common Caches

    registerBeanPostProcessors

  • 구체적인 코드는 다음과 같다.registerBeanPostProcessors 본 줄 코드는 바로 BeanPostProcessors를 등록하는 구체적인 코드는 다음과 같다.
  • public static void registerBeanPostProcessors(
                ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
    
            String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
    
            // Register BeanPostProcessorChecker that logs an info message when
            // a bean is created during BeanPostProcessor instantiation, i.e. when
            // a bean is not eligible for getting processed by all BeanPostProcessors.
            int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
            beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
    
            // Separate between BeanPostProcessors that implement PriorityOrdered,
            // Ordered, and the rest.
            List priorityOrderedPostProcessors = new ArrayList<>();
            List internalPostProcessors = new ArrayList<>();
            List orderedPostProcessorNames = new ArrayList<>();
            List nonOrderedPostProcessorNames = new ArrayList<>();
            for (String ppName : postProcessorNames) {
                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                    BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
                    priorityOrderedPostProcessors.add(pp);
                    if (pp instanceof MergedBeanDefinitionPostProcessor) {
                        internalPostProcessors.add(pp);
                    }
                }
                else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                    orderedPostProcessorNames.add(ppName);
                }
                else {
                    nonOrderedPostProcessorNames.add(ppName);
                }
            }
    
            // First, register the BeanPostProcessors that implement PriorityOrdered.
            sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
            registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
    
            // Next, register the BeanPostProcessors that implement Ordered.
            List orderedPostProcessors = new ArrayList<>();
            for (String ppName : orderedPostProcessorNames) {
                BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
                orderedPostProcessors.add(pp);
                if (pp instanceof MergedBeanDefinitionPostProcessor) {
                    internalPostProcessors.add(pp);
                }
            }
            sortPostProcessors(orderedPostProcessors, beanFactory);
            registerBeanPostProcessors(beanFactory, orderedPostProcessors);
    
            // Now, register all regular BeanPostProcessors.
            List nonOrderedPostProcessors = new ArrayList<>();
            for (String ppName : nonOrderedPostProcessorNames) {
                BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
                nonOrderedPostProcessors.add(pp);
                if (pp instanceof MergedBeanDefinitionPostProcessor) {
                    internalPostProcessors.add(pp);
                }
            }
            registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
    
            // Finally, re-register all internal BeanPostProcessors.
            sortPostProcessors(internalPostProcessors, beanFactory);
            registerBeanPostProcessors(beanFactory, internalPostProcessors);
    
            // Re-register post-processor for detecting inner beans as ApplicationListeners,
            // moving it to the end of the processor chain (for picking up proxies etc).
            beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
        }
    

    BeanPostProcessorChecker를 추가하면 BeanPostBean이 bean을 만들 때 정보를 출력하거나 불합격한 bean을 출력합니다
  • 그래서 위에서 알 수 있듯이 BeanDeifion이 BeanFactoryPostProcessor에서 확정
  • beanPostProcessor에서 최종 bean을 확정합니다. (bean은 초기화 종료 전후에 수정 bean을 얻을 수 있기 때문입니다.)
  • 네 가지 유형의 BeanPostProcessor 찾기 1.Priority Ordered 2 Ordered 3 rest 4 internal Post Processors 그 중에서 internal Post Processors는 Priority Ordered에 속하고 Ordered는 Merged Bean Definition Post Processor이며 주로 Root Bean Definition
  • 을 수정한다.
  • RootBeanDefinition은 여러 개의 원시 Bean 정의에서 유래할 수 있습니다(다른 bean 정의를 계승하여 일반적으로GenericBeanDefinitions로 등록되어 있습니다).RootBeanDefinition은 기본적으로 런타임 시 일관된 Bean 정의 뷰입니다.구성 단계에서 RootBeanDefinition은 독립된 bean 정의를 등록하는 데도 사용될 수 있습니다.하지만, Spring2.5 비안 정의를 프로그래밍해서 GenericBeanDefinition 클래스를 사용하는 것을 권장합니다.GenericBeanDefinition은 하드코딩이 아닌 동적 부모 의존을 허용하는 데 유리하다.
  • 그리고 순서대로 Priority Ordered Ordered를 등록하고 다른
  • 를 등록한다.
  • 최종적으로 Application Listener Detector를 추가했는데 주로 어떤 bean이 Application Listener인지 검사한다
  • initMessageSource


    이것은 국제화를 처리하는 것으로 구체적인 코드는 다음과 같다.
    protected void initMessageSource() {
            ConfigurableListableBeanFactory beanFactory = getBeanFactory();
            if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
                this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
                // Make MessageSource aware of parent MessageSource.
                if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
                    HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
                    if (hms.getParentMessageSource() == null) {
                        // Only set parent context as parent MessageSource if no parent MessageSource
                        // registered already.
                        hms.setParentMessageSource(getInternalParentMessageSource());
                    }
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Using MessageSource [" + this.messageSource + "]");
                }
            }
            else {
                // Use empty MessageSource to be able to accept getMessage calls.
                DelegatingMessageSource dms = new DelegatingMessageSource();
                dms.setParentMessageSource(getInternalParentMessageSource());
                this.messageSource = dms;
                beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
                if (logger.isDebugEnabled()) {
                    logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
                            "': using default [" + this.messageSource + "]");
                }
            }
        }
    
  • 메시지 Source의 bean이 있는지 먼저 검사합니다. 이 bean을 가져오고 부모 용기가 존재하면 부모 용기의 메시지 Source를 현재 용기의 부모 메시지 Source로 설정하고 부모 용기가 메시지 Source가 존재하지 않으면 부모 용기의 본체를 설정합니다.부모 메시지 소urce를 설정하는 의미는 메시지 소urce가 해석할 수 없으면 부모 메시지 소urce
  • 에 넘기는 것입니다
  • emtpymessageSource(DelegatingMessageSource)가 존재하지 않으면 상기 논리에 따라 부모MessageSource를 계속 설정하고 이 bean
  • 을 등록한다.

    initApplication Event Multicaster 초기화 컨테이너의 그룹 구성 요소

  • beanFactory.contains LocalBean(bean Name)은 현재 컨테이너에서 해당 beanName이 존재하는지만 찾습니다
  • .
    protected void initApplicationEventMulticaster() {
            ConfigurableListableBeanFactory beanFactory = getBeanFactory();
            if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
                this.applicationEventMulticaster =
                        beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
                if (logger.isDebugEnabled()) {
                    logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
                }
            }
            else {
                this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
                beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
                if (logger.isDebugEnabled()) {
                    logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
                            APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
                            "': using default [" + this.applicationEventMulticaster + "]");
                }
            }
        }
    
  • 상술한 방법은 현재 BeanName에 대응하는 Application Event Multicaster가 존재하는지 확인하고, 존재하면 이 bean이 존재하지 않으면 Simple Application Event Multicaster를 그룹 방송 구성 요소로 설정하는 것이다
  • onRefresh 코드는 다음과 같습니다.

        protected void onRefresh() {
            super.onRefresh();
            try {
                createWebServer();
            }
            catch (Throwable ex) {
                throw new ApplicationContextException("Unable to start web server", ex);
            }
        }
    
    public static ThemeSource initThemeSource(ApplicationContext context) {
            if (context.containsLocalBean(THEME_SOURCE_BEAN_NAME)) {
                ThemeSource themeSource = context.getBean(THEME_SOURCE_BEAN_NAME, ThemeSource.class);
                // Make ThemeSource aware of parent ThemeSource.
                if (context.getParent() instanceof ThemeSource && themeSource instanceof HierarchicalThemeSource) {
                    HierarchicalThemeSource hts = (HierarchicalThemeSource) themeSource;
                    if (hts.getParentThemeSource() == null) {
                        // Only set parent context as parent ThemeSource if no parent ThemeSource
                        // registered already.
                        hts.setParentThemeSource((ThemeSource) context.getParent());
                    }
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Using ThemeSource [" + themeSource + "]");
                }
                return themeSource;
            }
            else {
                // Use default ThemeSource to be able to accept getTheme calls, either
                // delegating to parent context's default or to local ResourceBundleThemeSource.
                HierarchicalThemeSource themeSource = null;
                if (context.getParent() instanceof ThemeSource) {
                    themeSource = new DelegatingThemeSource();
                    themeSource.setParentThemeSource((ThemeSource) context.getParent());
                }
                else {
                    themeSource = new ResourceBundleThemeSource();
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Unable to locate ThemeSource with name '" + THEME_SOURCE_BEAN_NAME +
                            "': using default [" + themeSource + "]");
                }
                return themeSource;
            }
        }
        private void createWebServer() {
            WebServer webServer = this.webServer;
            ServletContext servletContext = getServletContext();
            if (webServer == null && servletContext == null) {
                ServletWebServerFactory factory = getWebServerFactory();
                this.webServer = factory.getWebServer(getSelfInitializer());
            }
            else if (servletContext != null) {
                try {
                    getSelfInitializer().onStartup(servletContext);
                }
                catch (ServletException ex) {
                    throw new ApplicationContextException("Cannot initialize servlet context",
                            ex);
                }
            }
            initPropertySources();
        }
    
    
        protected void initPropertySources() {
            ConfigurableEnvironment env = getEnvironment();
            if (env instanceof ConfigurableWebEnvironment) {
                ((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, null);
            }
        }
    
        protected ServletWebServerFactory getWebServerFactory() {
            // Use bean names so that we don't consider the hierarchy
            String[] beanNames = getBeanFactory()
                    .getBeanNamesForType(ServletWebServerFactory.class);
            if (beanNames.length == 0) {
                throw new ApplicationContextException(
                        "Unable to start ServletWebServerApplicationContext due to missing "
                                + "ServletWebServerFactory bean.");
            }
            if (beanNames.length > 1) {
                throw new ApplicationContextException(
                        "Unable to start ServletWebServerApplicationContext due to multiple "
                                + "ServletWebServerFactory beans : "
                                + StringUtils.arrayToCommaDelimitedString(beanNames));
            }
            return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
        }
        public WebServer getWebServer(ServletContextInitializer... initializers) {
            Tomcat tomcat = new Tomcat();
            File baseDir = (this.baseDirectory != null ? this.baseDirectory
                    : createTempDir("tomcat"));
            tomcat.setBaseDir(baseDir.getAbsolutePath());
            Connector connector = new Connector(this.protocol);
            tomcat.getService().addConnector(connector);
            customizeConnector(connector);
            tomcat.setConnector(connector);
            tomcat.getHost().setAutoDeploy(false);
            configureEngine(tomcat.getEngine());
            for (Connector additionalConnector : this.additionalTomcatConnectors) {
                tomcat.getService().addConnector(additionalConnector);
            }
            prepareContext(tomcat.getHost(), initializers);
            return getTomcatWebServer(tomcat);
        }
    
    
        protected void prepareContext(Host host, ServletContextInitializer[] initializers) {
            File documentRoot = getValidDocumentRoot();
            TomcatEmbeddedContext context = new TomcatEmbeddedContext();
            if (documentRoot != null) {
                context.setResources(new LoaderHidingResourceRoot(context));
            }
            context.setName(getContextPath());
            context.setDisplayName(getDisplayName());
            context.setPath(getContextPath());
            File docBase = (documentRoot != null ? documentRoot
                    : createTempDir("tomcat-docbase"));
            context.setDocBase(docBase.getAbsolutePath());
            context.addLifecycleListener(new FixContextListener());
            context.setParentClassLoader(
                    this.resourceLoader != null ? this.resourceLoader.getClassLoader()
                            : ClassUtils.getDefaultClassLoader());
            resetDefaultLocaleMapping(context);
            addLocaleMappings(context);
            context.setUseRelativeRedirects(false);
            configureTldSkipPatterns(context);
            WebappLoader loader = new WebappLoader(context.getParentClassLoader());
            loader.setLoaderClass(TomcatEmbeddedWebappClassLoader.class.getName());
            loader.setDelegate(true);
            context.setLoader(loader);
            if (isRegisterDefaultServlet()) {
                addDefaultServlet(context);
            }
            if (shouldRegisterJspServlet()) {
                addJspServlet(context);
                addJasperInitializer(context);
            }
            context.addLifecycleListener(new StaticResourceConfigurer(context));
            ServletContextInitializer[] initializersToUse = mergeInitializers(initializers);
            host.addChild(context);
            configureContext(context, initializersToUse);
            postProcessContext(context);
        }
    
    public TomcatWebServer(Tomcat tomcat, boolean autoStart) {
            Assert.notNull(tomcat, "Tomcat Server must not be null");
            this.tomcat = tomcat;
            this.autoStart = autoStart;
            initialize();
        }
    
        private void initialize() throws WebServerException {
            TomcatWebServer.logger
                    .info("Tomcat initialized with port(s): " + getPortsDescription(false));
            synchronized (this.monitor) {
                try {
                    addInstanceIdToEngineName();
    
                    Context context = findContext();
                    context.addLifecycleListener((event) -> {
                        if (context.equals(event.getSource())
                                && Lifecycle.START_EVENT.equals(event.getType())) {
                            // Remove service connectors so that protocol binding doesn't
                            // happen when the service is started.
                            removeServiceConnectors();
                        }
                    });
    
                    // Start the server to trigger initialization listeners
                    this.tomcat.start();
    
                    // We can re-throw failure exception directly in the main thread
                    rethrowDeferredStartupExceptions();
    
                    try {
                        ContextBindings.bindClassLoader(context, context.getNamingToken(),
                                getClass().getClassLoader());
                    }
                    catch (NamingException ex) {
                        // Naming is not enabled. Continue
                    }
    
                    // Unlike Jetty, all Tomcat threads are daemon threads. We create a
                    // blocking non-daemon to stop immediate shutdown
                    startDaemonAwaitThread();
                }
                catch (Exception ex) {
                    stopSilently();
                    throw new WebServerException("Unable to start embedded Tomcat", ex);
                }
            }
        }
    
  • 상기 코드는 주로 ThemeSource를 초기화하는 것이다. 만약에 Resource Bundle ThemeSource를 설정하지 않으면 전체 논리는 메시지 Source
  • 와 유사하다.
  • WebServer 만들기
  • 웹 서버와 servletcontext가null이면 서브렛 웹서버 팩토리의 bean
  • 을 가져옵니다.
  • ServletContextInitializer가 존재하는 역할은 주로 ServletContextInitializer가spring 용기에 의해 관리되고 servlet 용기에 의해 관리되지 않으며 WebApplicationInitializer와 달리 ServletContextInitializer의 실현 클래스를 실현하고 WebApplicationInitializer가 실현되지 않으면 SpringServletContainerInitializer에 의해 감지되지 않기 때문에 servlet 용기가 자동으로 안내되지 않는다.그 onStartup 방법은 주로 Servlet Context를 설정하는 것이다. 예를 들어any servlets,filters,listeners context-params and attributes
  • WebApplicationInitializer는 Web라고 볼 수 있다.xml의 대체 인터페이스입니다.WebApplicationInitializer를 실현하면 servlet,listener 등을 추가할 수 있으며 웹 프로젝트를 불러올 때 이 인터페이스 구현 클래스를 불러와서 웹으로 만들 수 있습니다.xml 같은 역할
  • SpringServletContainerInitializer는 ServletContainerInitializer의 실현 클래스로서 SPI 메커니즘을 통해 웹 용기를 불러올 때 자동으로 호출됩니다.(이 클래스에는 @HandlesTypes에 대한 주석이 있습니다. 이 클래스의 역할은 관심 있는 일부 클래스를 Servlet Container Initializerde에 주입하는 것입니다.) 이 클래스의 방법은 웹application Initializer의 실현 클래스를 검색하여 온스타트랩 방법을 호출하여 웹을 시작하는 것입니다.xml과 같은 작용입니다.
  • getWebServer는 주로 내장tomcat 설정 커넥터(기본 Nio 프로토콜)customize 커넥터 조정 커넥터
  • 를 설정하고 시작합니다.
  • prepareContext는hosthost 내부에 있는spring의Tomcat EmbeddedContext
  • 를 설정하는 것이다
  • 마지막으로TomcatWeb 서버를 가져와 초기화합니다. 즉,Lifecycle Listener를 설정하고tomcat
  • 을 시작합니다.

    registerListeners

  • 는 주로 Application Listener를 등록한다. - 용기를 초기화한 후에 일부 데이터의 불러오기, 캐시 초기화, 특정 작업의 등록 등을 처리해야 한다.이 때 우리는 Spring이 제공하는 Application Listener를 사용하여 조작할 수 있다.
  • 그리고 earlyApplication Events
  • 발표

    finishBeanFactoryInitialization

  • beanFactory의conversion 서비스 설정(사실 자바빈스 PropertyEditors.의 대체자로서 속성 값을 변환하는 데 사용)
  • 포함된 값(예: 주석 속성)에 String 파서를 추가합니다.
  • 가능한 한 빨리 LoadTimeWeaverAwarebean을 초기화하여 변환기를 등록할 수 있도록 합니다.
  • temporary ClassLoader를null
  • 로 설정
  • 모든 BeanDefinition을 동결하고 변경할 수 없음
  • 실례 모든 게으름 피우지 않는 비안 대상
  • finishRefresh

  • 스캔된 ASM 메타데이터와 같은 컨텍스트 수준의 리소스 캐시를 지웁니다.
  • 용기를 초기화하는lifecycle processor 예를 들어smartLifeCycle
  • phase의 크기에 따라lifecycle 프로세스를 순서대로 시작합니다
  • ContextRefreshedEvent 발송 시간
  • LiveBeansView Mbean이 활성화되면 LiveBeansView Mbean에 참여합니다.

  • destroy Beans 모든 일례 파괴


    cancelRefresh active 를 false 로 표시


    resetCommonCaches

  • 반사된 캐시 지우기
  • 메모 관련 캐시 지우기
  • Clear the internal {@code ResolvableType}/{@code SerializableTypeWrapper} cache.
  • classloader 캐시 지우기
  • 내장 토마토캣 설명


    내장된 토마토캣의 의문점은 먼저 Servlet Web Server Factory의 bean을 만들고 get Web Server를 호출하여 웹 서버를 생성한 다음baseDir를 만듭니다. 프로토콜에 따라 Connector와Protocol Handler(프로토콜 프로세서)를 만듭니다. 이 Protocol Handler는 주로adapter와Endpoint를 설정하고adapter는connector adapter를 호출하여 서비스,prepare,asyncDispatch,log,check Recycled를 제공합니다.Domain 중에서domain은 이connector와 관련된 Mbeans를 등록한 다음에 서비스,connector,container(enigne)를 만드는 데 사용됩니다.valve를 추가하면 다음과 같은 관건이 옵니다.container의 순서는engine,host,context,wrapper입니다. 이쪽에서 Tomcat Embedded Context를 만들었습니다.스프링 컨테이너를 Tomcat Embed ded Context에 끼워넣고 Webapp Loader를 만들어서 현재 Tomcat Embed ded Context에 Wrapper를 끼워 넣습니다.MimeMappings 다음에tomcat을 시작합니다. 최종적으로servletWebServerApplicationContext의selfInitialize를 호출합니다. 주로spring용기와servletContext를 서로 연결합니다. 요청할 때tomcat는dispatchServlet을 호출하고 spring용기를 이servlet의 속성으로 설정하면 이servlet에서spring이 제공하는 기능을 사용할 수 있습니다.
    ProtocolHandler 내부에는 endpoint가 포함되어 있습니다. 즉, 이 프로토콜은 endpoint를 이용하여 밑바닥의 socket 통신을 할 수 있으며, Endpoint를 netty의 서버bootStrap으로 이해할 수 있습니다.
    endpoint에서 처리해야 할 socket을 발견하면 SocketProcessor를 만들고 최종적으로 ProtocolHandler의process 방법을 호출합니다. 이 방법은 Processor를 만듭니다. 이 Processor는 adapter를 포함하고 다른 요청 정보 등 최종적으로 adapter는 대응하는container에게 전달됩니다.
    -- Valve와 Container Background Processor는 일반적으로engine에 하나의 라인만 시작하여Container Background Processor를 실행하고 이 임무는 현재container와 그 하위 용기의background Process()를 수행한다.일반적인container의backgroundProcess는container 자체뿐만 아니라 이container의pipeline의valve의backgroundProcess도 포함한다
    일반적으로 요청을 수락하는 절차는Endpoint입니다.Acceptor의 acceptor 라인은 요청을 층층이 받아들여 Adapter에게 건네주고 Adapter는 주로 서비스 방법을 호출하여 org를 호출합니다.apache.coyote.Request req, org.apache.coyote.Response res 를 HttpServlet Request 및 HttpServlet Response 로 변환하여 engine 의 첫 번째 valve 처리
    용기마다 pipeline에 저장된 체인 테이블 valve가 있는데 마지막 valve는 다음 컨테이너를 연결하는 거예요.

    좋은 웹페이지 즐겨찾기