Springライフサイクルの3つの方法とソースの分析

36298 ワード

記事の目次
  • の3つの方法
  • コード例
  • 実行結果
  • @Scrope("singleton")--単一例
  • @Scope--プロトタイプ
  • ソースコード解析
  • 初期化方法
  • 廃棄方法
  • 3つの方法
  • @Ben指定初期化と廃棄方法
  • InitializingBenとDispable Bean
  • を実現します.
  • @PostConstruct&@Predestry
  • まず、実行順の初期化の実行手順3>2>1の破壊の実行手順3>2>1のソースコードを分析します.
    コードの例
    以下は3つの方法を一緒に使って、彼らの実行順を確認します.
    /**
     * @desc                 
     */
    @Component
    public class Role {
        public Role() {
            System.out.println("role===============");
        }
    }
    
    public class User implements InitializingBean, DisposableBean {
    
        @Autowired
        private Role role;
    
        public User() {
            System.out.println("user--constructor");
        }
    
        public void aaa() {
            System.out.println("user--aaa");
        }
    
        public void bbb() {
            System.out.println("user--bbb");
        }
    
        @Override
        //   DisposableBean   
        public void destroy() throws Exception {
            System.out.println("user++destory");
        }
    
        @Override
        //   InitializingBean   
        public void afterPropertiesSet() throws Exception {
            System.out.println("user++init");
        }
    
    
        @PostConstruct
        public void postConstructor() {
            System.out.println("postConstructor");
        }
    
        @PreDestroy
        public void preDestory() {
            System.out.println("preDestory");
        }
    }
    
    @Configuration
    @ComponentScan("com.demo.init")
    public class Test {
    
        // Bean          
        @Bean(initMethod = "aaa",destroyMethod = "bbb")
    //    @Scope("prototype")
        public User get(){
            return new User();
        }
    }
    
    //    
    public class Start {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Test.class);
            applicationContext.getBean(User.class);
            System.out.println("applicationContext will close");
            applicationContext.close();
        }
    }
    
    実行結果
    beanの役割領域を変更する
    @Scope(「singleton」)–単一例
    role===============
    user--constructor
    @postConstructor
    InitializingBean++init
    bean  init   aaa
    applicationContext will close
    @preDestory
    DisposableBean++destory
    bean destory  bbb
    
    @Scope(「prototype」)–プロトタイプ
    プロトタイプのbeanは呼び出し時のみ初期化されますので、aplication Contact.getBeanがなければ、userは初期化されません.beanFactoryに任せずに管理されますので、廃棄方法は実行されません.
    role===============
    user--constructor
    @postConstructor
    InitializingBean++init
    bean  init   aaa
    applicationContext will close
    
    ソース分析
    キーコードはソースのコメントに書いてあります.
    初期化の方法
    順番に次の方法に進みます.
  • org.springframe ework.com ntxt.support.AbstractAplication Contatext龚refresh
  • org.springframewark.com ntxt.support.AbstractAplication Contect t龚finish BeanFactory Initialization
  • org.spring frame ewark.beans.factory.co.figc.onfigrable Listable Beable Factory啱pre InstantiateSingletos
  • org.spring frame ewark.beans.factory.support.AbstractBeabin Factory啷ゲトビーン(java.lang.String)
  • org.springframe ewark.beans.factory.support.AbstractBenFactory咻doGetBen
  • org.spring frame ewark.beans.factory.support.AbstractBenFactory咻createBen
  • org.springframe ebook.beans.factory.support.AbstractAutowireCable BenFactory
  • org.spring frame ewark.beans.factory.support.Abstract AutowireCable BenFactory.java.lang.String,java.lang.Object,ort.org.sprigframe.bern.Beatonict.Ropt.246
    protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    		if (System.getSecurityManager() != null) {
    			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    				invokeAwareMethods(beanName, bean);
    				return null;
    			}, getAccessControlContext());
    		}
    		else {
    			invokeAwareMethods(beanName, bean);
    		}
    
    		Object wrappedBean = bean;
    		if (mbd == null || !mbd.isSynthetic()) {
                // @PostConstruct  CommonAnnotationBeanPostProcess   
                //          BeanPostProcessor   
    			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    		}
    
    		try {
                // 1.2             ,     
    			invokeInitMethods(beanName, wrappedBean, mbd);
    		}
    		catch (Throwable ex) {
    			throw new BeanCreationException(
    					(mbd != null ? mbd.getResourceDescription() : null),
    					beanName, "Invocation of init method failed", ex);
    		}
    		if (mbd == null || !mbd.isSynthetic()) {
    			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    		}
    
    		return wrappedBean;
    	}
    
    protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
    			throws Throwable {
    
    		boolean isInitializingBean = (bean instanceof InitializingBean);
    		if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
    			if (logger.isTraceEnabled()) {
    				logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
    			}
    			if (System.getSecurityManager() != null) {
    				try {
    					AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
    						((InitializingBean) bean).afterPropertiesSet();
    						return null;
    					}, getAccessControlContext());
    				}
    				catch (PrivilegedActionException pae) {
    					throw pae.getException();
    				}
    			}
    			else {
                    //          
                    //    InitializingBean afterPropertiesSet()  
    				((InitializingBean) bean).afterPropertiesSet();
    			}
    		}
    
    		if (mbd != null && bean.getClass() != NullBean.class) {
    			String initMethodName = mbd.getInitMethodName();
    			if (StringUtils.hasLength(initMethodName) &&
    					!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
    					!mbd.isExternallyManagedInitMethod(initMethodName)) {
                    
                    //      @Bean  init  
    				invokeCustomInitMethod(beanName, bean, mbd);
    			}
    		}
    	}
    
    廃棄方法
    appication Contect.close()は最終的に次のような方法org.spring frame ebook.beans.factory.support.Dispposable BenAdapterを実行します.
    注釈を見る
    public void destroy() {
    		if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
    			for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
    				//      @PreDestroy
                    processor.postProcessBeforeDestruction(this.bean, this.beanName);
    			}
    		}
    
    		if (this.invokeDisposableBean) {
    			if (logger.isTraceEnabled()) {
    				logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");
    			}
    			try {
    				if (System.getSecurityManager() != null) {
    					AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
    						((DisposableBean) this.bean).destroy();
    						return null;
    					}, this.acc);
    				}
    				else {
                        //        DisposableBean destroy()  
    					((DisposableBean) this.bean).destroy();
    				}
    			}
    			catch (Throwable ex) {
    				String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
    				if (logger.isDebugEnabled()) {
    					logger.warn(msg, ex);
    				}
    				else {
    					logger.warn(msg + ": " + ex);
    				}
    			}
    		}
    
    		if (this.destroyMethod != null) {
                //      @Bean       
    			invokeCustomDestroyMethod(this.destroyMethod);
    		}
    		else if (this.destroyMethodName != null) {
    			Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
    			if (methodToInvoke != null) {
    				invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
    			}
    		}
    	}