spring boot 실전 (13 편) 자동 배치 원리 분석

머리말
Spring Boot 에 자동 설정 을 도입 하여 개발 자 들 이 더욱 간편 하고 빠르게 이용 할 수 있 도록 합 니 다. 이 편 은 RabbitMQ 의 자동 설정 을 예 로 들 어 Spring Boot 의 자동 설정 원 리 를 분석 합 니 다.
스프링 부 트 는 기본적으로 커 넥 션 팩 토리, 래 빗 템 플 릿 등 bean 으로 설정 되 며, 앞의 글 에서 도 포 함 된 Tomcat 기본 설정 은 8080 포트 라 고 설명 했다.
이것들 은 모두 Spring Boot 자동 설정 의 범주 에 속 하 는데, 물론 자동 설정 이 상당히 많다.
EnableAutoConfiguration 설명
응용 프로그램 을 만 들 때 우 리 는 SpringBootApplication 주 해 를 사 용 했 습 니 다. spring boot 실전 (9 편) 응용 프로그램 생 성 소스 분석 에서 분석 한 적 이 있 습 니 다. 그 정 의 를 살 펴 보 겠 습 니 다.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Configuration
@EnableAutoConfiguration
@ComponentScan
public @interface SpringBootApplication {  
	Class<?>[] exclude() default {};

}

이 주석 에는 원 주석 @ EnableAutoConfiguration 이 존재 합 니 다. 이것 이 바로 Spring Boot 자동 설정 이 실 현 된 핵심 입구 입 니 다.정의:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({ EnableAutoConfigurationImportSelector.class,
		AutoConfigurationPackages.Registrar.class })
public @interface EnableAutoConfiguration {

	/**
	 * Exclude specific auto-configuration classes such that they will never be applied.
	 * @return the classes to exclude
	 */
	Class<?>[] exclude() default {};

}

특별한 주해 가 있 음 이 분명 하 다.
@ Import, 이 주 해 는 spring boot 실전 (10 편) Spring boot Bean 로드 소스 분석 에서 설명 되 었 습 니 다. bean 을 불 러 올 때 Import 주 해 를 해석 하기 때문에 이 코드 에 시선 을 집중 해 야 합 니 다.
@Import({ EnableAutoConfigurationImportSelector.class,
		AutoConfigurationPackages.Registrar.class })

EnableAutoConfigurationImportSelector
EnableAutoConfiguration ImportSelector 클래스 보기
public String[] selectImports(AnnotationMetadata metadata) {
		try {
			AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata
					.getAnnotationAttributes(EnableAutoConfiguration.class.getName(),
							true));

			Assert.notNull(attributes, "No auto-configuration attributes found. Is "
					+ metadata.getClassName()
					+ " annotated with @EnableAutoConfiguration?");

			// Find all possible auto configuration classes, filtering duplicates
			List<String> factories = new ArrayList<String>(new LinkedHashSet<String>(
					SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class,
							this.beanClassLoader)));

			// Remove those specifically disabled
			factories.removeAll(Arrays.asList(attributes.getStringArray("exclude")));

			// Sort
			factories = new AutoConfigurationSorter(this.resourceLoader)
					.getInPriorityOrder(factories);

			return factories.toArray(new String[factories.size()]);
		}
		catch (IOException ex) {
			throw new IllegalStateException(ex);
		}
	}

다음 코드 를 보 세 요. 클래스 경 로 를 가 져 오 는 spring. factories 에서 key 는 EnableAutoConfiguration 의 전체 제한 이름 대응 값 입 니 다.
SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class,
							this.beanClassLoader))

그 결 과 는:
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.hornetq.HornetQAutoConfiguration,\
org.springframework.boot.autoconfigure.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
org.springframework.boot.autoconfigure.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\
org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,\
org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,\
org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.velocity.VelocityAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.GzipFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration

이상 은 Spring Boot 의 모든 자동 설정 관련 클래스 입 니 다.시작 과정 에서 해당 클래스 설정 정 보 를 분석 하고 RabbitMQ 의 경우 RabbitAutoConfiguration 을 분석 합 니 다.
RabbitAutoConfiguration
우선 Rabbit AutoConfiguration 클래스 의 설명 을 살 펴 보 겠 습 니 다.
 
@Configuration
@ConditionalOnClass({ RabbitTemplate.class, Channel.class })
@EnableConfigurationProperties(RabbitProperties.class)
@Import(RabbitAnnotationDrivenConfiguration.class)
public class RabbitAutoConfiguration {
  • @ Configuration: 설명 이 필요 없 을 것 같 습 니 다
  • @ ConditionalOnClass: 대응 하 는 Class 파일 이 존재 할 때 만 Rabbit AutoConfiguration 을 해석 합 니 다. 그렇지 않 으 면 바로 건 너 뛰 고 해석 하지 않 습 니 다. 이것 도 RabbitMQ 를 가 져 오지 않 고 Jar 에 의존 할 때 프로젝트 가 정상적으로 시작 되 는 이유 입 니 다
  • @ EnableConfigurationProperties: @ ConfigurationProperties 에 대한 내장 지원 을 표시 합 니 다. 기본 값 은 Class 에 대응 하 는 것 을 bean 입 니 다. 예 를 들 어 이 값 은 RabbitProperties. class 로 정의 합 니 다.
  • @ConfigurationProperties(prefix = "spring.rabbitmq")
    public class RabbitProperties {
    
    	/**
    	 * RabbitMQ host.
    	 */
    	private String host = "localhost";
    
    	/**
    	 * RabbitMQ port.
    	 */
    	private int port = 5672;   .... //      }

    RabbitProperties 는 RabbitMQ 에 대한 설정 정 보 를 제공 합 니 다. 접 두 사 는 spring. rabbitmq 입 니 다. 따라서 전편 에 설 치 된 host, port 등 정 보 는 이 클래스 에 설 치 됩 니 다. 그 다음 @
    EnableConfigurationProperties 는 RabbitProperties 를 bean 으로 등록 합 니 다.
  • @ Import 가 져 오기 설정 을 위해 RabbitAnnotationDrivenConfiguration 은 다음 과 같이 구체 적 으로 실 현 됩 니 다.
  • @Configuration
    @ConditionalOnClass(EnableRabbit.class)
    class RabbitAnnotationDrivenConfiguration {
    
    	@Autowired(required = false)
    	private PlatformTransactionManager transactionManager;
    
    	@Bean
    	@ConditionalOnMissingBean(name = "rabbitListenerContainerFactory")
    	public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
    			ConnectionFactory connectionFactory) {
    		SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
    		factory.setConnectionFactory(connectionFactory);
    		if (this.transactionManager != null) {
    			factory.setTransactionManager(this.transactionManager);
    		}
    		return factory;
    	}
    
    	@EnableRabbit
    	@ConditionalOnMissingBean(name = RabbitListenerConfigUtils.RABBIT_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME)
    	protected static class EnableRabbitConfiguration {
    
    	}
    
    }

    여기에 또 하나의 중요 한 주석 이 포함 되 어 있 습 니 다. @ ConditionalOnMissingBean 은 지정 한 name 의 bean 이 존재 하면 이 주석 에 표 시 된 bean 을 만 들 지 않 습 니 다.
    @ConditionalOnMissingBean(name = "rabbitListenerContainerFactory")

    rabbit Listener Container Factory 라 는 bean 이 존재 한다 면 이 부분 코드 는 무시 합 니 다. 이것 은 Spring Boot 의 인성 화 된 표현 중 하나 입 니 다. 개발 자가 밝 힌 bean 이 첫 번 째 에 놓 여 있 습 니 다. 정말 예 의 를 잘 알 고 있 습 니 다 ~
    이 편 에서 언급 된 주해 가 비교적 많 고 그 구체 적 인 실현 원 리 는 나중에 시간 이 있 으 면 다시 구체 적 으로 분석 할 것 이다.
    Rabbit AutoConfiguration 류 의 구체 적 인 실현 으로 돌아 갑 니 다.
    먼저 보기:
    @Configuration
    	@ConditionalOnMissingBean(ConnectionFactory.class)
    	protected static class RabbitConnectionFactoryCreator {
    
    		@Bean
    		public ConnectionFactory rabbitConnectionFactory(RabbitProperties config) {
    			CachingConnectionFactory factory = new CachingConnectionFactory();
    			String addresses = config.getAddresses();
    			factory.setAddresses(addresses);
    			if (config.getHost() != null) {
    				factory.setHost(config.getHost());
    				factory.setPort(config.getPort());
    			}
    			if (config.getUsername() != null) {
    				factory.setUsername(config.getUsername());
    			}
    			if (config.getPassword() != null) {
    				factory.setPassword(config.getPassword());
    			}
    			if (config.getVirtualHost() != null) {
    				factory.setVirtualHost(config.getVirtualHost());
    			}
    			return factory;
    		}
    
    	}

    기본 Connection Factory 를 만 들 었 습 니 다. 주의 할 점 이 있 을 때, 이 Connection Factory 의 반전 없 는 설정 (전편 의 의문 을 풀 었 습 니 다)
    @Bean
    	@ConditionalOnMissingBean(RabbitTemplate.class)
    	public RabbitTemplate rabbitTemplate() {
    		return new RabbitTemplate(this.connectionFactory);
    	}

    기본 RabbitTemplate 만 들 기;다음 에 만 든 RabbitmessagingTemplate 가 맞습니다.
    래 빗 템 플 릿 의 포장.
    Rabbit AutoConfiguration 클래스 에 AmqpAdmin 생 성 이 남아 있 습 니 다. 설명 이 없 으 면 이 부분 은 다음 글 로 남 겨 두 고 설명 하 겠 습 니 다.

    좋은 웹페이지 즐겨찾기