Spring 탭 을 통 해 외부 프로필 가 져 오기

예시
먼저 프로필 이 외부 프로필 을 어떻게 가 져 오 는 지 볼 까요?spring-import 설정 파일 을 다음 과 같이 정의 합 니 다.

<?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.xsd">
   <import resource="spring-config.xml"/>
   <bean id="innerPerson" class="com.john.aop.Person">
   </bean>
</beans>
우 리 는 탭 을 정의 하고 가 져 온 자원 파일 을 spring-config.xml 로 속성 resource 로 설명 하 는 것 을 보 았 습 니 다.spring-config.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.xsd">
   <bean id="outerPerson" class="com.john.aop.Person">
          <property name="firstName" value="john"/>
            <property name="lastName" value="wonder"/>
   </bean>
   <bean id="ChineseFemaleSinger" class="com.john.beanFactory.Singer" abstract="true" >
      <property name="country" value="  "/>
      <property name="gender" value=" "/>
   </bean>
</beans>
그리고 우 리 는 spring-import 이 프로필 을 불 러 오기 위해 BeanFactory 를 실례 화 할 수 있 습 니 다.

public static void main(String[] args) {
   ApplicationContext context=new ClassPathXmlApplicationContext("spring-import.xml");
   Person outerPerson=(Person)context.getBean("outerPerson");
   System.out.println(outerPerson);
}
만약 문제 가 없다 면,우 리 는 outerPerson 이라는 bean 을 얻 고 인쇄 할 수 있 습 니 다.

Person [0, john wonder]
의 원리
스프링 이 import 탭 을 어떻게 분석 하고 가 져 온 프로필 을 불 러 오 는 지 원본 코드 를 통 해 분석 합 니 다.우선 DefaultBean Definition DocumentReader 클래스 에서 보 겠 습 니 다.
DefaultBeanDefinitionDocumentReader
우 리 는 클래스 에서 Public static final 을 정의 하 는 IMPORT 를 볼 수 있 습 니 다.ELEMENT 변수:

public static final String IMPORT_ELEMENT = "import";
그리고 이 변 수 를 사용 한 변 수 를 검색 하고 parseDefaultElement 함수 로 찾 을 수 있 습 니 다.
parseDefaultElement

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
   //todo    import       2020-11-17
   if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
      importBeanDefinitionResource(ele);
   }
}
이것 이 바로 우리 가 찾 는 외부 프로필 을 가 져 와 Bean 정의 소스 코드 를 불 러 옵 니 다.importBeanDefinitionResource 함 수 를 중점적으로 보 겠 습 니 다.
importBeanDefinitionResource

/**
 * Parse an "import" element and load the bean definitions
 * from the given resource into the bean factory.
 */
protected void importBeanDefinitionResource(Element ele) {
   ////    resource     
   String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
   ////   ,    
   if (!StringUtils.hasText(location)) {
      getReaderContext().error("Resource location must not be empty", ele);
      return;
   }
   // Resolve system properties: e.g. "${user.dir}"
   // //       ,    :"${user.dir}"
   location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);
   Set<Resource> actualResources = new LinkedHashSet<>(4);
   // Discover whether the location is an absolute or relative URI
   ////    location            
   boolean absoluteLocation = false;
   try {
      //  classpath*:    classpath:        
      absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
   }
   catch (URISyntaxException ex) {
      // cannot convert to an URI, considering the location relative
      // unless it is the well-known Spring prefix "classpath*:"
   }

   // Absolute or relative?
   //         loadBeanDefinitions
   if (absoluteLocation) {
      try {
         int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
         if (logger.isTraceEnabled()) {
            logger.trace("Imported " + importCount + " bean definitions from URL location [" + location + "]");
         }
      }
      catch (BeanDefinitionStoreException ex) {
         getReaderContext().error(
               "Failed to import bean definitions from URL location [" + location + "]", ele, ex);
      }
   }
   else {
      //       ,            Resource,      
      // No URL -> considering resource location as relative to the current file.
      try {
         int importCount;
         Resource relativeResource = getReaderContext().getResource().createRelative(location);

         //                     bean   
         if (relativeResource.exists()) {
            importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
            actualResources.add(relativeResource);
         }
         else {
            String baseLocation = getReaderContext().getResource().getURL().toString();
            //todo import        loadBeanDefinitions    2020-10-17
            importCount = getReaderContext().getReader().loadBeanDefinitions(
                  StringUtils.applyRelativePath(baseLocation, location), actualResources);
         }
         if (logger.isTraceEnabled()) {
            logger.trace("Imported " + importCount + " bean definitions from relative location [" + location + "]");
         }
      }
   }
}
이 코드 가 어떤 절차 인지 분석 해 보 겠 습 니 다.
1.우선 resource 탭 을 통 해 속성 값 을 분석 하고 문자열 값 이 비어 있 는 지 확인 합 니 다.
2.다음 에 현재 컨 텍스트 환경 을 통 해 문자열 경로 의 자리 표시 자 를 분석 할 것 입 니 다.이 점 은 이전 글 에서 분석 한 적 이 있 습 니 다.
2.다음 에 절대적 인 경로 인지 판단 하고 리 소스 PatternUtils.isUrl(location)||리 소스 Utils.touri(location).isAbsolute()를 호출 합 니 다.판단,중점:classpath*:또는 classpath:시작 을 절대 경로 로 하거나 URI 인 스 턴 스 를 생 성 할 수 있 습 니 다.절대 경로 로 생각 하거나 URI 의 isAbsolute 로 판단 할 수 있 습 니 다.
3.절대 경로 라면 getReader Context().getReader()를 통 해 XmlBeanDefinitionReader 를 가 져 온 다음 loadBeanDefinitions(String location,@Nullable Setactualrources)함 수 를 호출 합 니 다.
4.절대 경로 가 아니라면 현재 자원 에 대한 경 로 를 만 들 려 고 합 니 다.(이 점 은 매우 중요 합 니 다)이 프로필 에 있 는 BeanDefinitions 를 loadBeanDefinitions 방법 으로 불 러 옵 니 다.여기 서 우리 가 주의해 야 할 세부 사항 이 있 는데,바로 그것 이 왜 자원 의 존재 여 부 를 판단 하려 고 합 니까?존재 한다 면 loadBeanDefinitions(Resource resource)방법 을 직접 호출 하 는 것 입 니 다.즉,하나의 자원 파일 을 불 러 오 는 것 이 분명 합 니 다.방법 설명 과 같이:

/**
 * Load bean definitions from the specified XML file.
 * @param resource the resource descriptor for the XML file
 * @return the number of bean definitions found
 * @throws BeanDefinitionStoreException in case of loading or parsing errors
 */
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
   //load    BeanDefinition
   return loadBeanDefinitions(new EncodedResource(resource));
}
지정 한 xml 파일 에서 Bean 정 의 를 불 러 옵 니 다.존재 하지 않 는 다 면 절대 경로 와 마찬가지 로 loadBean Definitions(String location,@Nullable Setactualrources)함 수 를 호출 합 니 다.이 함수 의 정 의 를 살 펴 보 겠 습 니 다.

/**
 * Load bean definitions from the specified resource location.
 * <p>The location can also be a location pattern, provided that the
 * ResourceLoader of this bean definition reader is a ResourcePatternResolver.
 * @param location the resource location, to be loaded with the ResourceLoader
 * (or ResourcePatternResolver) of this bean definition reader
 * @param actualResources a Set to be filled with the actual Resource objects
 * that have been resolved during the loading process(                  *   ). May be {@code null}
 * to indicate that the caller is not interested in those Resource objects.
 */
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
이 location 은 지정 한 자원 경로 에서 BeanDefinitions 를 불 러 오 는 것 을 말 합 니 다.
총결산
원본 코드 를 통 해 알 수 있 듯 이 외부 에서 프로필 을 가 져 오 는 것 은 하나의 전체 프로필 을 통 해 각 단일 프로필 확장 을 불 러 올 수 있 는 기 회 를 주 는 것 입 니 다.
이상 은 Spring 이탭 을 통 해 외부 프로필 을 가 져 오 는 상세 한 내용 입 니 다.Spring 가 져 오 는 외부 프로필 에 대한 자 료 는 다른 관련 글 을 주목 하 십시오!

좋은 웹페이지 즐겨찾기