Spring 에서 bean 의 초기 화 와 소각 몇 가지 실현 방식 에 대한 상세 한 설명
[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 초기 화 전후 처리 작업
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 의 초기 화 와 소각 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 저 를 많이 사랑 해 주세요!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[MeU] Hashtag 기능 개발➡️ 기존 Tag 테이블에 존재하지 않는 해시태그라면 Tag , tagPostMapping 테이블에 모두 추가 ➡️ 기존에 존재하는 해시태그라면, tagPostMapping 테이블에만 추가 이후에 개발할 태그 기반 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.