JavaRush /Java Blog /Random-KO /스프링 프레임워크. 소개
Marchello
레벨 20
Санкт-Петербург

스프링 프레임워크. 소개

Random-KO 그룹에 게시되었습니다
안녕하세요! JavaRush 관리가 새로운 수준에서 작업하는 동안 저는 Spring Framework에 대한 일련의 교육 기사를 시작하고 싶습니다. 예, 인터넷에 이미 이 주제에 관한 많은 자료가 있다는 것을 알고 있지만 실습에서 알 수 있듯이 모두 Hello World 수준에 있습니다. 저는 주석을 올바르게 배치하는 방법이 아니라 이 모든 것이 "내부적으로" 어떻게 작동하는지에 대해 이야기하고 싶습니다. 이 글은 이미 어떤 방식으로든 이 프레임워크를 사용해본 경험이 있고 기본 개념에 익숙한 사람들을 대상으로 작성되었습니다. 스프링 프레임워크.  소개 - 1

컨텍스트를 초기화하는 중입니다.

이제 기본부터 시작하겠습니다. 제 생각에는 가장 중요한 점 중 하나는 컨텍스트가 어떻게 설정되고 Bean이 초기화되는지 이해하는 것입니다. 아시 다시피 Spring이 작동하기 전에 구성해야 합니다. 대홍수 이전에는 xml 파일을 사용하여 이 작업을 수행했습니다(일부 프로젝트, 주로 오래된 프로젝트에서는 오늘날까지 계속 이 작업을 수행합니다). 다음은 이러한 구성 파일의 작은 예입니다.
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id="helloWorld" class="ru.javarush.HelloWorld">
       <property name="message" value="Hello World!"/>
   </bean>

</beans>
전반적으로 이것은 두 개의 컨트롤러를 만들고 스타트업을 시작하기에 충분합니다(이륙하지는 않습니다). 하지만 이 구성으로 Spring이 어떻게 작동하게 될까요? 그리고 여기서 일이 흥미로워집니다. Spring이 우리의 구성을 이해하기 위해서는 XmlBeanDefinitionReader. 이것은 xml을 스캔(파싱)하고 거기에 작성한 내용을 기반으로 BeanDefinition을 생성하는 내부 Spring 구성 요소입니다. BeanDefinitionBean에 대한 정보를 저장하는 객체입니다. 여기에는 다음이 포함됩니다. 해당 클래스(빈)가 생성되어야 하는 클래스; 범위; 지연 초기화가 설치되어 있는지 여부 이 Bean 전에 xml에 설명된 다른 속성과 다른 속성을 초기화해야 합니까? 수신된 모든 BeanDefinition는 에 추가되며 HashMap, 여기서 식별자는 Bean(사용자가 설정하거나 Spring에서 할당한)의 이름과 BeanDefinition객체 자체입니다. 모든 것이 만들어진 후 BeanDefinition새로운 영웅이 무대에 등장합니다 - BeanFactory. HashMap’e이 객체는 s를 반복하고 BeanDefinition이를 기반으로 빈을 생성하여 IoC 컨테이너에 넣습니다. 실제로 여기에는 미묘한 차이가 있습니다. 애플리케이션이 시작되면 IoC 컨테이너에는 싱글톤 범위(기본적으로 설정됨)가 있는 Bean이 포함되고 나머지는 필요할 때(프로토타입, 요청, 세션) 생성됩니다. 이제 약간의 여담으로 다른 캐릭터에 대해 알아 보겠습니다.

BeanPostProcessor를 만나보세요. (BPP)

빈 포스트 프로세서사실 빈은 애플리케이션의 비즈니스 로직 클래스가 아닐 수도 있습니다. 빈은 인프라 빈(Infrastructure Bean)이라고도 합니다. 간단히 말해서 인프라 빈은 비즈니스 로직 빈(예, 빈이 너무 많음)을 구성하는 클래스입니다. 이에 대한 자세한 내용은 아래에서 설명하겠지만 BPP가 정확히 무엇을 구성하는지 좀 더 명확하게 설명하기 위해 예를 들어보겠습니다. 다들 요약을 잘 아시죠 @Autowired? 따라서 AutowiredAnnotationBeanPostProcessor모든 클래스가 서로 내장되어 있는지 확인하는 것은 귀하의 책임입니다. 영국의

BeanFactory로 돌아가자

HashMap이제 BPP에 대해 알았으므로 을 반복할 때 모든 가 먼저 생성되어 별도로 배치된다는 점을 명확히 해야 합니다 BeanDefinition(IoC 컨테이너가 아님) BeanPostProcessor. 그런 다음 비즈니스 로직의 일반 Bean이 생성되어 IoC 컨테이너에 배치되며 별도로 지연된 BPP를 사용하여 구성이 시작됩니다. 이것이 일어나는 방식입니다. 각 BPP에는 2가지 방법이 있습니다.
postProcessorBeforeInitialization(Object bean, String beanName);
postProcessorAfterInitialization(Object bean, String beanName);
bin을 두 번 반복합니다. 메소드가 처음 호출될 때 postProcessorBeforeInitialization와 두 번째로 메소드가 호출될 때 postProcessorAfterInitialization. 왜 두 가지 방법이 필요한지에 대한 의문이 생겼습니다. 설명하겠습니다. 사실은 일부 주석(예: @Transactional)을 처리하기 위해 Bean이 프록시 클래스로 대체된다는 것입니다. 이것이 수행되는 이유를 이해하려면 작동 방식을 알아야 하며 @Transactional이것이 작동하는 방식입니다. 이 주석으로 표시된 메서드에 즉시 몇 줄의 코드를 추가해야 합니다. 어떻게 하나요? 맞습니다. 프록시 클래스를 생성하면 필요한 코드가 필요한 메서드에 추가됩니다. 이제 이런 상황을 상상해 보세요. 수업이 있습니다.
class A {
    @Autowired
    private SomeClass someClass;

    @Transactional
    public void method() {
        // модификатор доступа обязательно public
    }
}
이 클래스에는 2개의 주석 @Autowired@Transactional. 두 주석 모두 서로 다른 BPP에 의해 처리됩니다. 먼저 작동하면 AutowiredBPP모든 것이 괜찮지만 그렇지 않으면 이 문제에 직면하게 됩니다. 사실 프록시 클래스가 생성되면 모든 메타 정보가 손실됩니다. 즉, @Autowired프록시 클래스의 주석에 대한 정보가 없으므로 AutowiredBPP작동하지 않습니다. 이는 우리 필드가 someClass값을 가지게 되어 nullNPE로 이어질 가능성이 높다는 것을 의미합니다. 메소드 호출 사이에 -method가 있는 경우 호출 postProcessorBeforeInitialization된다는 점도 알아두는 것이 좋습니다 . 이것은 기본적으로 두 번째 생성자이지만 차이점은 현재 모든 종속성이 이미 클래스에 포함되어 있으며 -method에서 액세스할 수 있다는 것입니다. 따라서 다시 한 번 컨텍스트 초기화 알고리즘은 다음과 같습니다. postProcessorAfterInitializationinitinit
  1. XmlBeanDefinitionReaderxml 구성 파일을 스캔합니다.
  2. 을(를) 만들어서 BeanDefinition넣습니다 HashMap.
  3. 오고 BeanFactory이것으로부터 HashMap모든 '를 별도로 합산합니다 BeanPostProcessor.
  4. BeanDefinition에서 빈을 생성하여 IoC 컨테이너에 배치합니다.
  5. 여기서 BPP는 두 가지 방법을 사용하여 이러한 Bean을 구성합니다.
  6. 준비가 된.
사실 그게 전부입니다. 기사가 마음에 들었고 그러한 튜토리얼을 계속 작성할 가치가 있는지 작성하십시오.
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION