Spring 에서 bean 의 초기 화 와 소각 몇 가지 실현 방식 에 대한 상세 한 설명

Bean 의 생명주기:bean 대상 C 속성 할당 C 초기 화 방법 을 만 듭 니 다.
[1]init-method 와 destroy-method
사용자 정의 초기 화 방법 과 소각 방법 두 가지 방식:xml 설정 과 주석.
① xml 설정

<bean id="person" 
  class="com.core.Person" scope="singleton" 
  init-method="init" destroy-method="cleanUp"
  autowire="byName" lazy-init="true" > 
</bean> 
② 주석 설정

	@Scope("singleton")
  @Lazy
  @Bean(name="person",initMethod="init",destroyMethod="cleanUp",
  autowire=Autowire.BY_NAME)
  public Person person01(){
    return new Person("lisi", 20);
  }
단일 인 스 턴 스 bean 은 용기 생 성 이 완료 되 기 전에 생 성 되 고 초기 화 되 며 용기 가 소 각 될 때 소 각 됩 니 다.다 중 인 스 턴 스 bean(scope=prototype)은 이 bean 인 스 턴 스 를 처음 가 져 올 때 만 만 만 들 고 초기 화 되 며 용 기 는 이 bean 의 소각 을 책임 지지 않 습 니 다.
[2]Initializing Bean 과 Disposable Bean
 InitialingBean 인터페이스:

public interface InitializingBean {
	void afterPropertiesSet() throws Exception;
}
BeanFactory 에서 bean 속성 을 설정 한 후 실행
bean 이 구현 해 야 할 인터페이스 입 니 다.bean 의 속성 이 BeanFactory 에 설정 되면 반응 해 야 합 니 다.예 를 들 어 사용자 정의 초기 화 를 실행 하거나 모든 강제 속성 이 설정 되 어 있 는 지 확인 해 야 합 니 다.
InitializingBean 을 실현 하 는 대체 가능 한 방식 은 bean 에 사용자 정의 init-method 를 지정 하 는 것 입 니 다.예 를 들 어 xml bean 정의 에 있 습 니 다.
bean 의 속성 설정 후 작업 을 진행 합 니 다.값 을 되 돌려 주지 않 지만 이상 을 던 질 수 있 습 니 다.
DisposableBean 인터페이스:

public interface DisposableBean {
	void destroy() throws Exception;
}
bean 에 의 해 실 현 된 인 터 페 이 스 는 소각 할 때 자원 을 방출 하고 Bean 이 소각 할 때 이 방법 을 사용 합 니 다.
캐 시 를 없 애 는 단일 예 를 들 면,BeanFactory 가 이 없 애 는 방법 을 사용 할 수 있 습 니 다.
용기 가 닫 혔 을 때,상하 문 을 사용 하면 모든 단일 bean 을 소각 합 니 다.
Disposable Bean 인 터 페 이 스 를 대체 하 는 방안 은 xml bean 정의 와 같은 사용자 정의 destroy-method 방법 을 지정 합 니 다.
사용자 정의 bean 은 상기 두 개의 인 터 페 이 스 를 실현 합 니 다.

@Component
public class Cat implements InitializingBean,DisposableBean {
	
	public Cat(){
		System.out.println("cat constructor...");
	}

	@Override
	public void destroy() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("cat...destroy...");
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("cat...afterPropertiesSet...");
	}

}
테스트 결과
cat constructor...
cat...afterPropertiesSet...
용기 생 성 완료...
4 월 08,2018 6:35:46 오후 org.springframework.context.annotation.annotationConfigApplicationContext
doClose
정보:org.springframework.context.annotation 를 닫 습 니 다.AnnotationConfigApplicationContext@11028347:
startup date [Sun Apr 08 18:35:46 CST 2018]; root of context hierarchy
cat...destroy...
【3】@PostConstruct 와@PreDestroy
JSR 250 규범 정의 두 개의 주 해 를 사용 합 니 다:
@PostConstruct:PostConstruct 주해 작용 은 방법 상 주입 에 의존 한 후 초기 화 작업 을 합 니 다.이 방법 은 클래스 가 service 에 들 어가 기 전에 호출 되 며,모든 의존 항목 주입 을 지원 하 는 클래스 는 이 주 해 를 지원 해 야 합 니 다.
@PreDestroy:용기 가 bean 을 소각 하기 전에 청소 작업 을 하 라 고 알려 주세요.
사용자 정의 클래스 는 상기 두 개의 주 해 를 사용 합 니 다.

@Component
public class Dog implements ApplicationContextAware {
	
	//@Autowired
	private ApplicationContext applicationContext;
	
	public Dog(){
		System.out.println("dog constructor...");
	}
	
	//           
	@PostConstruct
	public void init(){
		System.out.println("Dog....@PostConstruct...");
	}
	
	//        
	@PreDestroy
	public void detory(){
		System.out.println("Dog....@PreDestroy...");
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		// TODO Auto-generated method stub
		this.applicationContext = applicationContext;
	}

}
테스트 결 과 는 다음 과 같다.
dog constructor...
Dog....@PostConstruct...
용기 생 성 완료...
4 월 08,2018 6:42:11 오후 org.springframework.context.annotation.annotationConfigApplicationContext
doClose
정보:org.springframework.context.annotation 를 닫 습 니 다.AnnotationConfigApplicationContext@11028347:
startup date [Sun Apr 08 18:42:10 CST 2018]; root of context hierarchy
Dog....@PreDestroy...
【4】BeanPostProcessor-Bean 백업 프로세서
 ① bean 백업 프로세서 가 무엇 입 니까?
bean 초기 화 전후 처리 작업
  • postprocessBeforeInitialization:초기 화 전에 작업
  • post Process After Initialization:초기 화 후 작업
  • 그 인터페이스 원본 코드 는 다음 과 같다.
    
    public interface BeanPostProcessor {
    
    	Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    	
    	Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
    }
    
    사용자 정의 MyBeanPostProcessor 이 인터페이스 구현:
    
    /**
     *      :           
     *             
     * @author lfy
     */
    @Component
    public class MyBeanPostProcessor implements BeanPostProcessor {
    
    	@Override
    	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    		// TODO Auto-generated method stub
    	System.out.println("BeanPostProcessor.postProcessBeforeInitialization..."+beanName+"=>"+bean);
    		return bean;
    	}
    
    	@Override
    	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    		// TODO Auto-generated method stub
    		System.out.println("BeanPostProcessor.postProcessAfterInitialization..."+beanName+"=>"+bean);
    		return bean;
    	}
    
    }
    
    
    ② BeanPostProcessor 원리
    AbstractAutowireCapableBean Factory 에서 bean 과 BeanPostProcessor 에 대한 실행 순 서 는 위 에서 아래로
    
    // bean      
    populateBean(beanName, mbd, instanceWrapper);
    //    initializeBean  
    Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd)
    {
    	applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    	//        
    	invokeInitMethods(beanName, wrappedBean, mbd);
    	applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    
    AbstractAutowireCapableBeanFactory.initializeBean 원본 코드 는 다음 과 같 습 니 다:
    
    protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    		if (System.getSecurityManager() != null) {
    			AccessController.doPrivileged(new PrivilegedAction<Object>() {
    				@Override
    				public Object run() {
    					invokeAwareMethods(beanName, bean);
    					return null;
    				}
    			}, getAccessControlContext());
    		}
    		else {
    		//    /    
    			invokeAwareMethods(beanName, bean);
    		}
    
    		Object wrappedBean = bean;
    		if (mbd == null || !mbd.isSynthetic()) {
    		//  bean          
    			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    		}
    		//       
    		try {
    			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()) {
    		//	//  bean          
    			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    		}
    		return wrappedBean;
    	}
    
    AbstractAutowireCapableBeanFactory.invokeInitMethods 방법 원본 코드 는 다음 과 같 습 니 다.
    
    protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
    			throws Throwable {
    
    		boolean isInitializingBean = (bean instanceof InitializingBean);
    		if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
    			if (logger.isDebugEnabled()) {
    				logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
    			}
    			//  InitializingBean.afterPropertiesSet
    			if (System.getSecurityManager() != null) {
    				try {
    					AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
    						@Override
    						public Object run() throws Exception {
    							((InitializingBean) bean).afterPropertiesSet();
    							return null;
    						}
    					}, getAccessControlContext());
    				}
    				catch (PrivilegedActionException pae) {
    					throw pae.getException();
    				}
    			}
    			else {
    				((InitializingBean) bean).afterPropertiesSet();
    			}
    		}
    //          
    		if (mbd != null) {
    			String initMethodName = mbd.getInitMethodName();
    			if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
    					!mbd.isExternallyManagedInitMethod(initMethodName)) {
    				invokeCustomInitMethod(beanName, bean, mbd);
    			}
    		}
    	}
    
    【5】봄 밑바닥 은 BeanPostProcessor 를 사용한다.
    Spring 프레임 밑 에 대량의 BeanPostProcessor 가 존재 하 는데 다음 과 같다.
    这里写图片描述
    예제 1:BeanValidationPostProcessor 는 bean 검사 처리
    Javadoc 는 다음 과 같 습 니 다.
    
    /**
     * Simple {@link BeanPostProcessor} that checks JSR-303 constraint annotations
     * in Spring-managed beans, throwing an initialization exception in case of
     * constraint violations right before calling the bean's init method (if any).
     *
     * @author Juergen Hoeller
     * @since 3.0
     */
    public class BeanValidationPostProcessor implements BeanPostProcessor, InitializingBean {
    
    	private Validator validator;
    
    	private boolean afterInitialization = false;
    	//...
    }
    
    
    예제 2:applicationContextAware Processor 는 용기 컨 텍스트 를 가 져 오 는 데 도움 을 줍 니 다.
    Javadoc 는 다음 과 같 습 니 다.
    
    /**
     * {@link org.springframework.beans.factory.config.BeanPostProcessor}
     * implementation that passes the ApplicationContext to beans that
     * implement the {@link EnvironmentAware}, {@link EmbeddedValueResolverAware},
     * {@link ResourceLoaderAware}, {@link ApplicationEventPublisherAware},
     * {@link MessageSourceAware} and/or {@link ApplicationContextAware} interfaces.
     *
     * <p>Implemented interfaces are satisfied in order of their mention above.
     *
     * <p>Application contexts will automatically register this with their
     * underlying bean factory. Applications do not use this directly.
     *
     * @author Juergen Hoeller
     * @author Costin Leau
     * @author Chris Beams
     * @since 10.10.2003
     * @see org.springframework.context.EnvironmentAware
     * @see org.springframework.context.EmbeddedValueResolverAware
     * @see org.springframework.context.ResourceLoaderAware
     * @see org.springframework.context.ApplicationEventPublisherAware
     * @see org.springframework.context.MessageSourceAware
     * @see org.springframework.context.ApplicationContextAware
     * @see org.springframework.context.support.AbstractApplicationContext#refresh()
     */
    class ApplicationContextAwareProcessor implements BeanPostProcessor {
    
    	private final ConfigurableApplicationContext applicationContext;
    
    	private final StringValueResolver embeddedValueResolver;
    	//...
    }
    
    예 를 들 어[3]중의 dog 류 를 예 로 들 면 debug 설명도 가 다음 과 같다.
    这里写图片描述
    【6】초기 화 및 소각 방식 테스트
    ① 만약 에 하나의 bean 이 다음 과 같은 여섯 가지 방식 을 종합 적 으로 응용 한다 면 집행 순 서 는 어떻게 될 까?
    Bean 클래스 는 다음 과 같 습 니 다:
    
    public class Person implements InitializingBean,DisposableBean {
      private String name;
      private Integer age=1;
    
      public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
        System.out.println("Person(String name, Integer age) constructor"+this);
      }
      public Person() {
        super();
        System.out.println("Person() constructor"+age);
      }
    
      public Integer getAge() {
        return age;
      }
    
      public void setAge(Integer age) {
        this.age = age;
      }
    
      public String getName() {
        return name;
      }
    
      public void setName(String name) {
        this.name = name;
      }
    
      @Override
      public String toString() {
        return "Person{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
      }
    	//    init  
      public void init(){
        System.out.println("-----Person.init()-----"+this);
      }
      //        
      public void cleanUp(){
        System.out.println("-----Person.cleanUp()-----"+this);
      }
    	// InitializingBean     
      @Override
      public void afterPropertiesSet() throws Exception {
        System.out.println("-----InitializingBean.afterPropertiesSet()-----"+this);
      }
    	//DisposableBean      
      @Override
      public void destroy() throws Exception {
        System.out.println("-----DisposableBean.destroy()-----"+this);
      }
    
      //           
      @PostConstruct
      public void init2(){
        System.out.println("-----@PostConstruct-----"+this);
      }
    
      //        
      @PreDestroy
      public void destory2(){
        System.out.println("-----@PreDestroy-----"+this);
      }
    }
    
    설정 클래스 는 다음 과 같 습 니 다:
    
    public class Person implements InitializingBean,DisposableBean {
      private String name;
      private Integer age=1;
    
      public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
        System.out.println("Person(String name, Integer age) constructor"+this);
      }
      public Person() {
        super();
        System.out.println("Person() constructor"+age);
      }
    
      public Integer getAge() {
        return age;
      }
    
      public void setAge(Integer age) {
        this.age = age;
      }
    
      public String getName() {
        return name;
      }
    
      public void setName(String name) {
        this.name = name;
      }
    
      @Override
      public String toString() {
        return "Person{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
      }
    	//    init  
      public void init(){
        System.out.println("-----Person.init()-----"+this);
      }
      //        
      public void cleanUp(){
        System.out.println("-----Person.cleanUp()-----"+this);
      }
    	// InitializingBean     
      @Override
      public void afterPropertiesSet() throws Exception {
        System.out.println("-----InitializingBean.afterPropertiesSet()-----"+this);
      }
    	//DisposableBean      
      @Override
      public void destroy() throws Exception {
        System.out.println("-----DisposableBean.destroy()-----"+this);
      }
    
      //           
      @PostConstruct
      public void init2(){
        System.out.println("-----@PostConstruct-----"+this);
      }
    
      //        
      @PreDestroy
      public void destory2(){
        System.out.println("-----@PreDestroy-----"+this);
      }
    }
    
    테스트 결 과 는 다음 과 같다.
    
    //       
    Person(String name, Integer age) constructorPerson{name='lisi', age=20}
    -----@PostConstruct-----Person{name='lisi', age=20}
    -----InitializingBean.afterPropertiesSet()-----Person{name='lisi', age=20}
    -----Person.init()-----Person{name='lisi', age=20}
    
    //      
    -----@PreDestroy-----Person{name='lisi', age=20}
    -----DisposableBean.destroy()-----Person{name='lisi', age=20}
    -----Person.cleanUp()-----Person{name='lisi', age=20}
    
    즉,bean 의 구조 기 를 bean 속성 할당 으로 가장 먼저 사용 한 다음 에 JSR 250 규범 에 따라 정 의 된 두 개의 주 해 를 사용 합 니 다.그 다음은 InitialingBean 과 Disposable Bean 인터페이스 이 고 마지막 으로 우리 가 사용자 정의 초기 화 방법 과 소각 방법 입 니 다.여기 에는 아직 빈 포스트 프로세서 가 도입 되 지 않 았 음 을 주의 하 세 요.
    ② ① 에 BeanPostProcessor 추가
    bean 을 예화 하고 초기 화 합 니 다.
    
    //      
    Person(String name, Integer age) constructorPerson{name='lisi', age=20}
    //bean    
    BeanPostProcessor.postProcessBeforeInitialization...person=>Person{name='lisi', age=20}
    //     
    -----@PostConstruct-----Person{name='lisi', age=20}
    -----InitializingBean.afterPropertiesSet()-----Person{name='lisi', age=20}
    -----Person.init()-----Person{name='lisi', age=20}
    //bean      
    BeanPostProcessor.postProcessAfterInitialization...person=>Person{name='lisi', age=20}
    
    과정 은 다음 과 같다. -->BeanPostProcessor-->@PostConstruct-->InitializingBean-->init()-->BeanPostProcessor콩 을 소각 하 다
    
    -----@PreDestroy-----Person{name='lisi', age=20}
    -----DisposableBean.destroy()-----Person{name='lisi', age=20}
    -----Person.cleanUp()-----Person{name='lisi', age=20}
    
    전체 그림 은 다음 과 같다.
    在这里插入图片描述
    bean 의 구조 함 수 를 호출 할 때 입 참 에 따라 bean 속성 으로 값 을 부여 합 니 다.입 참 이 비어 있 으 면 bean 속성 에 기본 값 을 부여 합 니 다.인용 유형 은 null 이 고 기본 유형 은 int 가 0 입 니 다.
    [7]@Autowired 주해 의 값 은 언제 넣 습 니까?
    다음 과 같이 redisTemplate 이 의존 도 는 언제 용기 에 RedisController 에 주입 되 나 요?
    在这里插入图片描述
    위의 분석 을 통 해 알 수 있 듯 이 의존 주입 은@PostConstruct 주해 의 방법 이 호출 되 기 전에 완 료 된 것 입 니 다 populateBean() .
    在这里插入图片描述
    그렇다면 구체 적 으로 언제 어떤 종류 가 완 성 된@Autowired 주해 주입 의존 도 는?
    클래스 가 실례 화 된 후에 BeanPostProcessor 가 완성 한 것 은 어느 BeanPostProcessor 입 니까?
    구체 적 으로AutowiredAnnotationBeanPostProcessor에 의 해 완성 되 었 다.
    在这里插入图片描述
    여기 서 Spring 중 bean 의 초기 화 와 소각 에 관 한 몇 가지 실현 방식 에 대한 상세 한 설명 은 여기까지 입 니 다.더 많은 관련 Spring 중 bean 의 초기 화 와 소각 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 저 를 많이 사랑 해 주세요!

    좋은 웹페이지 즐겨찾기