JavaRush /Java Blog /Random-KO /종속성 주입 또는 "CDI가 또 무엇입니까?"에 대한 짧은 여행입니다.
Viacheslav
레벨 3

종속성 주입 또는 "CDI가 또 무엇입니까?"에 대한 짧은 여행입니다.

Random-KO 그룹에 게시되었습니다
현재 가장 널리 사용되는 프레임워크가 구축되는 기반은 종속성 주입입니다. 이에 대해 CDI 사양이 말하는 내용, 우리가 가지고 있는 기본 기능 및 이를 어떻게 사용할 수 있는지 살펴보는 것이 좋습니다.
의존성 주입에 대한 간략한 소개 또는

소개

나는 이 짧은 리뷰를 CDI와 같은 것에 바치고 싶습니다. 이게 뭔가요? CDI는 컨텍스트 및 종속성 주입을 나타냅니다. 이는 종속성 주입 및 컨텍스트를 설명하는 Java EE 사양입니다. 자세한 내용은 웹사이트 http://cdi-spec.org 를 참조하세요 . CDI는 사양(작동 방식에 대한 설명, 인터페이스 집합)이므로 이를 사용하려면 구현도 필요합니다. 이러한 구현 중 하나는 Weld입니다. - http://weld.cdi-spec.org/ 종속성을 관리하고 프로젝트를 생성하려면 Maven을 사용합니다. - https://maven.apache.org 따라서 Maven이 설치되었으므로 이제 실제로는 그것을 이해할 것입니다. 그래서 초록을 이해하지 못합니다. 이를 위해 Maven을 사용하여 프로젝트를 생성하겠습니다. 명령줄을 열고(Windows에서는 Win+R을 사용하여 "실행" 창을 열고 cmd를 실행할 수 있음) Maven에게 모든 작업을 수행하도록 요청해 보겠습니다. 이를 위해 Maven에는 Maven Archetype 이라는 개념이 있습니다 .
의존성 주입에 대한 간략한 소개 또는
그런 다음 " 숫자 선택 또는 필터 적용 " 및 " org.apache.maven.archetypes:maven-archetype-quickstart 버전 선택 " 질문에서 Enter 키를 누르기만 하면 됩니다. 다음으로, 소위 GAV라고 불리는 프로젝트 식별자를 입력합니다( 명명 규칙 가이드 참조 ).
의존성 주입에 대한 간략한 소개 또는
프로젝트가 성공적으로 생성되면 "BUILD SUCCESS"라는 문구가 표시됩니다. 이제 우리가 선호하는 IDE에서 프로젝트를 열 수 있습니다.

프로젝트에 CDI 추가

소개에서 우리는 CDI에 흥미로운 웹사이트( http://www.cdi-spec.org/ )가 있다는 것을 알았습니다 . 필요한 데이터가 포함된 테이블이 포함된 다운로드 섹션이 있습니다.
의존성 주입에 대한 간략한 소개 또는
여기서는 Maven이 프로젝트에서 CDI API를 사용한다는 사실을 어떻게 설명하는지 볼 수 있습니다. API는 애플리케이션 프로그래밍 인터페이스, 즉 일부 프로그래밍 인터페이스입니다. 우리는 이 인터페이스 뒤에서 인터페이스가 어떻게 작동하는지 걱정하지 않고 인터페이스를 사용하여 작업합니다. API는 프로젝트에서 사용하기 시작할 jar 아카이브입니다. 즉, 프로젝트가 이 jar에 의존하기 시작합니다. 따라서 우리 프로젝트의 CDI API는 종속성입니다. Maven에서 프로젝트는 POM.xml 파일( POM - Project Object Model )에 설명되어 있습니다. 종속성은 종속성 블록에 설명되어 있으며 여기에 새 항목을 추가해야 합니다.
<dependency>
	<groupId>javax.enterprise</groupId>
	<artifactId>cdi-api</artifactId>
	<version>2.0</version>
</dependency>
아시다시피, 제공된 값으로 범위를 지정하지 않습니다. 왜 그런 차이가 있습니까? 이 범위는 누군가가 우리에게 종속성을 제공한다는 것을 의미합니다. 애플리케이션이 Java EE 서버에서 실행된다는 것은 서버가 필요한 모든 JEE 기술을 애플리케이션에 제공한다는 의미입니다. 이 검토를 단순화하기 위해 Java SE 환경에서 작업하므로 누구도 이러한 종속성을 제공하지 않습니다. 종속성 범위에 대한 자세한 내용은 " 종속성 범위 " 에서 확인할 수 있습니다 . 좋습니다. 이제 인터페이스를 사용하여 작업할 수 있습니다. 하지만 구현도 필요합니다. 기억나는 대로 Weld를 사용하겠습니다. 어디에서나 서로 다른 종속성이 제공된다는 점이 흥미롭습니다. 그러나 우리는 문서를 따를 것입니다. 그러므로 " 18.4.5. 클래스 경로 설정 "을 읽고 다음과 같이 해보자:
<dependency>
	<groupId>org.jboss.weld.se</groupId>
	<artifactId>weld-se-core</artifactId>
	<version>3.0.5.Final</version>
</dependency>
Weld의 세 번째 라인 버전이 CDI 2.0을 지원하는 것이 중요합니다. 따라서 우리는 이 버전의 API를 믿을 수 있습니다. 이제 코드를 작성할 준비가 되었습니다.
의존성 주입에 대한 간략한 소개 또는

CDI 컨테이너 초기화

CDI는 메커니즘입니다. 누군가는 이 메커니즘을 통제해야 합니다. 위에서 이미 읽었듯이 그러한 관리자는 컨테이너입니다. 따라서 이를 생성해야 하며 SE 환경에서는 그 자체가 나타나지 않습니다. 기본 메소드에 다음을 추가해 보겠습니다.
public static void main(String[] args) {
	SeContainerInitializer initializer = SeContainerInitializer.newInstance();
	initializer.addPackages(App.class.getPackage());
	SeContainer container = initializer.initialize();
}
CDI 컨테이너를 수동으로 생성한 이유는 다음과 같습니다. 우리는 SE 환경에서 일합니다. 일반적인 전투 프로젝트에서 코드는 다양한 기술을 코드에 제공하는 서버에서 실행됩니다. 따라서 서버가 CDI를 제공하는 경우 이는 서버에 이미 CDI 컨테이너가 있으므로 아무것도 추가할 필요가 없음을 의미합니다. 하지만 이 튜토리얼에서는 SE 환경을 사용하겠습니다. 또한 컨테이너는 명확하고 이해하기 쉽게 여기에 있습니다. 왜 컨테이너가 필요한가요? 내부 용기에는 원두(CDI 빈)가 들어있습니다.
의존성 주입에 대한 간략한 소개 또는

CDI 콩

그럼, 콩. CDI 빈이란 무엇입니까? 이것은 몇 가지 규칙을 따르는 Java 클래스입니다. 이러한 규칙은 사양의 " 2.2. Bean은 어떤 종류의 클래스인가요? " 장에 설명되어 있습니다. App 클래스와 동일한 패키지에 CDI Bean을 추가해 보겠습니다.
public class Logger {
    public void print(String message) {
        System.out.println(message);
    }
}
이제 우리는 main메소드에서 이 빈을 호출할 수 있습니다:
Logger logger = container.select(Logger.class).get();
logger.print("Hello, World!");
보시다시피 new 키워드를 사용하여 Bean을 생성하지 않았습니다. 우리는 CDI 컨테이너에 "CDI 컨테이너입니다. Logger 클래스의 인스턴스가 꼭 필요합니다. 저에게 주세요."라고 물었습니다. 이 방법을 " 종속성 조회 ", 즉 종속성을 검색한다고 합니다. 이제 새 클래스를 만들어 보겠습니다.
public class DateSource {
    public String getDate() {
        return new Date().toString();
    }
}
날짜의 텍스트 표현을 반환하는 기본 클래스입니다. 이제 메시지에 날짜 출력을 추가해 보겠습니다.
public class Logger {
    @Inject
    private DateSource dateSource;

    public void print(String message) {
        System.out.println(dateSource.getDate() + " : " + message);
    }
}
흥미로운 @Inject 주석이 나타났습니다. CDI 용접 문서의 " 4.1. 주입점 " 장에 설명된 대로 이 주석을 사용하여 주입점을 정의합니다. 러시아어에서는 이를 "구현 지점"이라고 읽을 수 있습니다. Bean을 인스턴스화할 때 종속성을 주입하기 위해 CDI 컨테이너에서 사용됩니다. 보시다시피 dateSource 필드에는 어떤 값도 할당되지 않습니다. 그 이유는 CDI 컨테이너가 내부 CDI Bean(자체적으로 인스턴스화한 Bean, 즉 관리하는 Bean만)이 " 종속성 주입 "을 사용할 수 있도록 허용하기 때문입니다. 이는 Inversion of Control 의 또 다른 방법으로 , 우리가 명시적으로 개체를 생성하는 대신 종속성을 다른 사람이 제어하는 ​​접근 방식입니다. 종속성 주입은 메서드, 생성자 또는 필드를 통해 수행될 수 있습니다. 자세한 내용은 CDI 사양 장 " 5.5. 종속성 주입 "을 참조하세요. 구현해야 할 사항을 결정하는 절차를 유형 안전 확인이라고 하며 이에 대해 이야기해야 합니다.
의존성 주입에 대한 간략한 소개 또는

이름 확인 또는 Typesafe 확인

일반적으로 인터페이스는 구현할 개체 유형으로 사용되며 CDI 컨테이너 자체에서 선택할 구현을 결정합니다. 이는 여러 가지 이유로 유용하며 이에 대해 논의하겠습니다. 따라서 로거 인터페이스가 있습니다.
public interface Logger {
    void print(String message);
}
그는 로거가 있으면 메시지를 보낼 수 있고 로그 작업을 완료할 것이라고 말합니다. 이 경우 어떻게, 어디서 관심을 끌지 않을 것입니다. 이제 로거에 대한 구현을 만들어 보겠습니다.
public class SystemOutLogger implements Logger {
    @Inject
    private DateSource dateSource;

    public void print(String message) {
        System.out.println(message);
    }
}
보시다시피 이것은 System.out에 쓰는 로거입니다. 아주 멋진. 이제 우리의 주요 방법은 이전과 같이 작동할 것입니다. Logger logger = container.select(Logger.class).get(); 이 줄은 로거에서 계속 수신됩니다. 그리고 장점은 인터페이스만 알면 되며 CDI 컨테이너는 이미 구현에 대해 생각하고 있다는 것입니다. 로그를 원격 저장소로 보내야 하는 두 번째 구현이 있다고 가정해 보겠습니다.
public class NetworkLogger implements Logger {
    @Override
    public void print(String message) {
        System.out.println("Send log message to remote log system");
    }
}
이제 코드를 변경하지 않고 실행하면 오류가 발생합니다. CDI 컨테이너는 인터페이스의 두 가지 구현을 확인하며 둘 중 하나를 선택할 수 없습니다. org.jboss.weld.exceptions.AmbiguousResolutionException: WELD-001335: Ambiguous dependencies for type Logger 무엇을 해야 합니까? 다양한 변형이 가능합니다. 가장 간단한 것은 CDI 컨테이너가 이 클래스를 CDI 빈으로 인식하지 못하도록 하는 CDI 빈에 대한 @Vetoed 주석입니다. 그러나 훨씬 더 흥미로운 접근 방식이 있습니다. Weld CDI 문서의 " 4.7. Alternatives@Alternative " 장 에 설명된 주석을 사용하여 CDI Bean을 "대체"로 표시할 수 있습니다 . 무슨 뜻이에요? 이는 명시적으로 사용하지 않는 한 선택되지 않음을 의미합니다. 이는 Bean의 대체 버전입니다. NetworkLogger 빈을 @Alternative로 표시하면 코드가 다시 실행되어 SystemOutLogger에서 사용되는 것을 볼 수 있습니다. 대안을 활성화하려면 beans.xml 파일이 있어야 합니다 . " beans.xml, 어디에 두나요? " 라는 질문이 생길 수 있습니다. 따라서 파일을 올바르게 배치해 보겠습니다.
의존성 주입에 대한 간략한 소개 또는
이 파일이 있으면 코드가 포함된 아티팩트를 " Explicit bean archive "라고 합니다. 이제 소프트웨어와 XML이라는 두 가지 별도의 구성이 있습니다. 문제는 동일한 데이터를 로드한다는 것입니다. 예를 들어, DataSource 빈 정의는 2번 로드되고 프로그램이 실행될 때 충돌이 발생합니다. CDI 컨테이너는 이를 2개의 개별 Bean으로 간주합니다(실제로 CDI 컨테이너가 두 번 학습한 동일한 클래스임에도 불구하고). 이를 방지하려면 다음 두 가지 옵션이 있습니다.
  • 줄을 제거 initializer.addPackages(App.class.getPackage())하고 xml 파일에 대안 표시를 추가합니다.
<beans
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://xmlns.jcp.org/xml/ns/javaee
        http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd">
    <alternatives>
        <class>ru.javarush.NetworkLogger</class>
    </alternatives>
</beans>
  • bean-discovery-mode값이 " none "인 속성을 Bean 루트 요소에 추가 하고 프로그래밍 방식으로 대안을 지정하십시오.
initializer.addPackages(App.class.getPackage());
initializer.selectAlternatives(NetworkLogger.class);
따라서 CDI 대안을 사용하면 컨테이너는 선택할 Bean을 결정할 수 있습니다. 흥미롭게도 CDI 컨테이너가 동일한 인터페이스에 대한 여러 대안을 알고 있는 경우 주석을 사용하여 우선순위를 표시하여 알 수 있습니다 @Priority(CDI 1.1부터).
의존성 주입에 대한 간략한 소개 또는

예선

별도로 예선과 같은 것에 대해 논의 할 가치가 있습니다. 규정자는 Bean 위의 주석으로 표시되며 Bean 검색을 구체화합니다. 이제 더 자세한 내용을 살펴보겠습니다. 흥미롭게도 모든 CDI Bean에는 최소한 하나의 한정자가 있습니다 @Any. Bean 위에 어떤 한정자를 지정하지 않았지만 CDI 컨테이너 자체가 @Any한정자에 또 다른 한정자를 추가하는 경우 - @Default. 아무 것도 지정하면(예: @Any를 명시적으로 지정) @Default 한정자는 자동으로 추가되지 않습니다. 하지만 예선의 장점은 자신만의 예선을 만들 수 있다는 것입니다. 한정자는 주석과 거의 다르지 않습니다. 본질적으로 이것은 특별한 방법으로 작성된 주석일 뿐입니다. 예를 들어 프로토콜 유형으로 Enum을 입력할 수 있습니다.
public enum ProtocolType {
    HTTP, HTTPS
}
다음으로 이 유형을 고려하는 한정자를 만들 수 있습니다.
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface Protocol {
    ProtocolType value();
    @Nonbinding String comment() default "";
}
@Nonbinding로 표시된 필드는 한정자 결정에 영향을 미치지 않는다는 점에 유의할 가치가 있습니다 . 이제 한정자를 지정해야 합니다. 이는 Bean 유형(CDI가 이를 정의하는 방법을 알 수 있도록) 위와 주입 지점(@Inject 주석을 사용하여 이 위치에서 주입을 찾을 Bean을 이해할 수 있도록) 위에 표시됩니다. 예를 들어 한정자를 사용하여 일부 클래스를 추가할 수 있습니다. 단순화를 위해 이 문서에서는 NetworkLogger 내에서 해당 작업을 수행합니다.
public interface Sender {
	void send(byte[] data);
}

@Protocol(ProtocolType.HTTP)
public static class HTTPSender implements Sender{
	public void send(byte[] data) {
		System.out.println("sended via HTTP");
	}
}

@Protocol(ProtocolType.HTTPS)
public static class HTTPSSender implements Sender{
	public void send(byte[] data) {
		System.out.println("sended via HTTPS");
	}
}
그런 다음 Inject를 수행할 때 어떤 클래스가 사용될지에 영향을 미치는 한정자를 지정합니다.
@Inject
@Protocol(ProtocolType.HTTPS)
private Sender sender;
그렇죠?) 아름다워 보이는데 왜 그런지는 불분명합니다. 이제 다음을 상상해 보세요.
Protocol protocol = new Protocol() {
	@Override
	public Class<? extends Annotation> annotationType() {
		return Protocol.class;
	}
	@Override
	public ProtocolType value() {
		String value = "HTTP";
		return ProtocolType.valueOf(value);
	}
};
container.select(NetworkLogger.Sender.class, protocol).get().send(null);
이 방법으로 값 가져오기를 재정의하여 동적으로 계산할 수 있습니다. 예를 들어 일부 설정에서 가져올 수 있습니다. 그런 다음 프로그램/서버를 다시 컴파일하거나 다시 시작하지 않고도 즉시 구현을 변경할 수 있습니다. 훨씬 더 흥미로워지죠? )
의존성 주입에 대한 간략한 소개 또는

생산자

CDI의 또 다른 유용한 기능은 생산자입니다. 이는 일부 Bean이 종속성 주입을 요청할 때 호출되는 특수 메소드(특수 주석으로 표시됨)입니다. 자세한 내용은 문서의 " 2.2.3. 생산자 방법 " 섹션에 설명되어 있습니다. 가장 간단한 예:
@Produces
public Integer getRandomNumber() {
	return new Random().nextInt(100);
}
이제 Integer 유형의 필드에 주입할 때 이 메서드가 호출되고 여기에서 값을 가져옵니다. 여기서 우리는 new 키워드를 볼 때 이것이 CDI 빈이 아니라는 것을 즉시 이해해야 합니다. 즉, Random 클래스의 인스턴스는 CDI 컨테이너를 제어하는 ​​것(이 경우 생산자)에서 파생되었다는 이유만으로 CDI Bean이 되지 않습니다.
의존성 주입에 대한 간략한 소개 또는

인터셉터

인터셉터는 작업을 "간섭"하는 인터셉터입니다. CDI에서는 이것이 매우 명확하게 수행됩니다. 인터프리터(또는 인터셉터)를 사용하여 로깅을 수행하는 방법을 살펴보겠습니다. 먼저 인터셉터에 대한 바인딩을 설명해야 합니다. 많은 경우와 마찬가지로 이 작업도 주석을 사용하여 수행됩니다.
@Inherited
@InterceptorBinding
@Target({TYPE, METHOD})
@Retention(RUNTIME)
public @interface ConsoleLog {
}
@InterceptorBinding여기서 가장 중요한 것은 이것이 확장( )에 의해 상속되는 인터셉터( )에 대한 바인딩이라는 것입니다 @InterceptorBinding. 이제 인터셉터 자체를 작성해 보겠습니다.
@Interceptor
@ConsoleLog
public class LogInterceptor {
    @AroundInvoke
    public Object log(InvocationContext ic) throws Exception {
        System.out.println("Invocation method: " + ic.getMethod().getName());
        return ic.proceed();
    }
}
스펙의 예제에서 인터셉터가 작성되는 방법에 대해 자세히 읽을 수 있습니다: " 1.3.6. 인터셉터 예제 ". 자, 우리가 해야 할 일은 인셉터를 켜는 것뿐입니다. 이렇게 하려면 실행 중인 메서드 위에 바인딩 주석을 지정하세요.
@ConsoleLog
public void print(String message) {
이제 또 다른 매우 중요한 세부 사항이 있습니다. 인터셉터는 기본적으로 비활성화되어 있으며 대안과 동일한 방식으로 활성화해야 합니다. 예를 들어 beans.xml 파일에서 다음과 같습니다 .
<interceptors>
	<class>ru.javarush.LogInterceptor</class>
</interceptors>
보시다시피 아주 간단합니다.
의존성 주입에 대한 간략한 소개 또는

이벤트 및 관찰자

CDI는 또한 이벤트 및 관찰자 모델을 제공합니다. 여기서는 인터셉터만큼 모든 것이 명확하지 않습니다. 따라서 이 경우 Event는 절대적으로 모든 클래스가 될 수 있으며 설명에는 특별한 것이 필요하지 않습니다. 예를 들어:
public class LogEvent {
    Date date = new Date();
    public String getDate() {
        return date.toString();
    }
}
이제 누군가가 이벤트를 기다려야 합니다.
public class LogEventListener {
    public void logEvent(@Observes LogEvent event){
        System.out.println("Message Date: " + event.getDate());
    }
}
여기서 가장 중요한 것은 @Observes 주석을 지정하는 것입니다. 이는 이것이 단순한 메서드가 아니라 LogEvent 유형의 이벤트 관찰 결과로 호출되어야 하는 메서드임을 나타냅니다. 자, 이제 우리는 지켜볼 사람이 필요합니다:
public class LogObserver {
    @Inject
    private Event<LogEvent> event;
    public void observe(LogEvent logEvent) {
        event.fire(logEvent);
    }
}
이벤트 유형 LogEvent에 대해 이벤트 이벤트가 발생했음을 컨테이너에 알리는 단일 메서드가 있습니다. 이제 남은 것은 관찰자를 사용하는 것뿐입니다. 예를 들어 NetworkLogger에서는 관찰자 주입을 추가할 수 있습니다.
@Inject
private LogObserver observer;
그리고 print 메소드에서는 관찰자에게 새로운 이벤트가 있음을 알릴 수 있습니다.
public void print(String message) {
	observer.observe(new LogEvent());
이벤트는 하나의 스레드 또는 여러 스레드에서 처리될 수 있다는 점을 아는 것이 중요합니다. .fireAsync비동기 처리의 경우 .fire 대신 메서드 와 @ObservesAsync@Observes 대신 주석을 사용합니다. 예를 들어, 모든 이벤트가 서로 다른 스레드에서 실행되는 경우 한 스레드가 예외를 발생시키면 다른 스레드는 다른 이벤트에 대한 작업을 수행할 수 있습니다. 평소와 같이 " 10. 이벤트 " 장의 사양에서 CDI의 이벤트에 대한 자세한 내용을 읽을 수 있습니다 .
의존성 주입에 대한 간략한 소개 또는

데코레이터

위에서 본 것처럼 CDI 윙 아래에는 다양한 디자인 패턴이 모여있습니다. 그리고 여기 또 하나가 있습니다 - 데코레이터. 이것은 매우 흥미로운 일입니다. 이 수업을 살펴 ​​보겠습니다.
@Decorator
public abstract class LoggerDecorator implements Logger {
    public final static String ANSI_GREEN = "\u001B[32m";
    public static final String ANSI_RESET = "\u001B[0m";

    @Inject
    @Delegate
    private Logger delegate;

    @Override
    public void print(String message) {
        delegate.print(ANSI_GREEN + message + ANSI_RESET);
    }
}
데코레이터를 선언함으로써 Logger 구현이 사용될 때 이 "추가 기능"이 사용되며 실제 구현을 알고 대리자 필드에 저장됩니다(주석으로 표시되므로 @Delegate). 데코레이터는 인터셉터도 데코레이터도 아닌 CDI Bean에만 연관될 수 있습니다. 사양 " 1.3.7. 데코레이터 예제 "에서도 예제를 볼 수 있습니다. 인터셉터와 마찬가지로 데코레이터도 켜져 있어야 합니다. 예를 들어 beans.xml 에서는 다음과 같습니다 .
<decorators>
	<class>ru.javarush.LoggerDecorator</class>
</decorators>
자세한 내용은 용접 참조: " 10장. 데코레이터 "를 참조하세요.

수명주기

콩은 자신만의 생명주기를 가지고 있습니다. 다음과 같이 보입니다.
의존성 주입에 대한 간략한 소개 또는
그림에서 볼 수 있듯이 소위 수명 주기 콜백이 있습니다. 이는 Bean 라이프사이클의 특정 단계에서 특정 메소드를 호출하도록 CDI 컨테이너에 지시하는 주석입니다. 예를 들어:
@PostConstruct
public void init() {
	System.out.println("Inited");
}
이 메소드는 CDI Bean이 컨테이너에 의해 인스턴스화될 때 호출됩니다. 더 이상 필요하지 않은 빈이 파괴될 때 @PreDestroy에서도 동일한 일이 발생합니다. 약어 CDI에 문자 C-Context가 포함되어 있는 것은 아무것도 아닙니다. CDI의 Bean은 상황에 따라 다릅니다. 즉, 수명 주기는 CDI 컨테이너 내에 존재하는 상황에 따라 달라집니다. 이를 더 잘 이해하려면 사양 섹션 " 7. 상황별 인스턴스의 수명 주기 " 를 읽어야 합니다 . 컨테이너 자체에도 수명 주기가 있다는 사실도 알아두는 것이 좋습니다. " 컨테이너 수명 주기 이벤트 "에서 이에 대해 읽을 수 있습니다.
의존성 주입에 대한 간략한 소개 또는

위에서 우리는 CDI라는 빙산의 일각을 살펴보았습니다. CDI는 JEE 사양의 일부이며 JavaEE 환경에서 사용됩니다. Spring을 사용하는 사람들은 CDI를 사용하지 않고 DI를 사용하는데, 즉 약간씩 다른 스펙이다. 그러나 위의 사항을 알고 이해하면 쉽게 마음을 바꿀 수 있습니다. Spring이 CDI 세계(동일한 Inject)의 주석을 지원한다는 점을 고려하십시오. 추가 자료: #비아체슬라프
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION