스프링은 어떤 라이브러리, 클래스가 이 프로젝트에 포함되어있는가? 를 기준으로 자동 구성을 설정합니다.
어떤 라이브러리, 클래스가 이 프로젝트에 포함되어있는지를 확인하는 방법은 너무 복잡하기에 스프링에서 유틸리티를 지원합니다.
ClassUtils
를 사용하면 됩니다.
value
는 Condition에서 읽을 수 있는 값을 저장하기 위해 선언하였습니다.
즉, 어떤한 클래스가 존재하는지 체크할수 있는 클래스의 이름을 전달합니다.
value
를 가져다 사용 할 수 있는 MyOnClassCondition
를 새로 구현하여 사용할 것입니다.
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Conditional(MyOnClassCondition.class)
public @interface ConditionalMyOnClass {
String value();
}
value
를 가져다 ClassUtils.isPresent('value') 안에 넣어서 클래스가 존재하는지 확인하고, 존재한다면 Bean으로 등록하게 됩니다!
public class MyOnClassCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Map<String, Object> attrs = metadata.getAnnotationAttributes(ConditionalMyOnClass.class.getName());
String value = (String) attrs.get("value");
return ClassUtils.isPresent(value, context.getClassLoader());
}
}
커스텀한 MyOnCalass어노테이션을 사용해 Bean으로 등록하면 됩니다!
@ConditionalMyOnClass("org.apache.catalina.startup.Tomcat")
@MyAutoConfiguration
@ConditionalMyOnClass("org.apache.catalina.startup.Tomcat")
public class TomcatWebServerConfig {
@Bean("tomcatWebServerFactory")
public ServletWebServerFactory servletWebServerFactory(){
return new TomcatServletWebServerFactory();
}
}
@MyAutoConfiguration
@ConditionalMyOnClass("org.eclipse.jetty.server.Server")
public class JettyWebServerConfig {
@Bean("jettyWebServerFactory")
public ServletWebServerFactory servletWebServerFactory(){
return new JettyServletWebServerFactory();
}
}
이때 build.gradle에서 Tomcat역할을 하는 것이 2개라면 충돌을 발생합니다.
Unable to start ServletWebServerApplicationContext
due to multiple ServletWebServerFactory beans : tomcatWebServerFactory,jettyWebServerFactory
따라서 하나만 선택하여 서버를시작하면 됩니다!
dependencies {
implementation ('org.springframework.boot:spring-boot-starter-web'){
exclude group : 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
}
implementation 'org.springframework.boot:spring-boot-starter-jetty'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
현재 구조
스프링 부트도 기본적으로 build.gradle에 등록된 라이브러리를 기준으로 작동합니다.
따라서 같은 기능을 하는 라이브러리가 2개이상이라면 오류가 발생합니다!
어떻게 스프링 부트가 자동구성정보를 설정하는지 알게되었고, 스프링에는 다양한 기능들이 정말 많다고 느꼈습니다.