CodeGym /Java Blog /무작위의 /게으른 사람들을 위한 Spring 기초, 기본 개념 및 코드 예제. 2 부
John Squirrels
레벨 41
San Francisco

게으른 사람들을 위한 Spring 기초, 기본 개념 및 코드 예제. 2 부

무작위의 그룹에 게시되었습니다
이전 글 에서 Spring이 무엇인지, Bean과 Context가 무엇인지에 대해 간략히 설명드렸습니다. 이제 사용해 볼 시간입니다. IntelliJ IDEA Enterprise Edition을 사용하여 해보겠습니다. 그러나 모든 예제는 무료 IntelliJ IDEA Community Edition에서도 작동해야 합니다. 스크린샷에서 내가 가지고 있지 않은 창이 보이더라도 걱정하지 마세요. 이 프로젝트에서는 중요하지 않습니다 :) 게으른 사람들을 위한 Spring 기초, 기본 개념 및 코드 예제.  파트 2 - 1먼저 빈 Maven 프로젝트를 만듭니다. 이 링크 의 문서에서 이 작업을 수행하는 방법을 보여 주었습니다 . " It's time to convert our Maven project into a web project. " 라는 문구까지 읽어보세요 . — 그 후 문서에서는 웹 프로젝트를 만드는 방법을 보여주지만 지금 당장은 필요하지 않습니다. src/main/java 에서폴더를 만들고 패키지를 만듭니다(제 경우에는 " 이라고 했습니다 en.codegym.info.fatfaggy.animals. 원하는 대로 이름을 지정할 수 있습니다. 모든 올바른 위치에서 내 패키지 이름을 패키지 이름으로 바꾸는 것을 잊지 마십시오. 이제 클래스를 Main만들고 방법

public static void main(String[] args) {
    ...
}
그런 다음 pom.xml 파일을 열고 dependencies섹션을 추가합니다. 이제 Maven 저장소 로 이동하여 최신 안정 버전에 대한 Spring 컨텍스트를 찾으십시오 . 우리가 찾은 것을 dependencies섹션에 넣으십시오. 다른 CodeGym 기사 에서 이 프로세스에 대해 자세히 설명했습니다 (" Maven에서 종속성 연결 " 섹션 참조 ). 그런 다음 Maven 자체가 필요한 종속성을 찾아 다운로드합니다. 최종적으로 다음과 같은 결과를 얻을 수 있습니다. 게으른 사람들을 위한 Spring 기초, 기본 개념 및 코드 예제.  파트 2 - 2왼쪽 창에서 패키지와 클래스가 포함된 프로젝트 구조를 볼 수 있습니다 Main. 중간 창에는 pom.xml이 나를 찾는 방법이 표시됩니다. 나는 또한 속성을 추가그것에 섹션. 이 섹션은 내가 소스 파일에서 사용하고 있는 Java 버전과 컴파일할 버전을 Maven에 알려줍니다. 이는 내가 이전 버전의 Java를 사용하고 있다는 IDEA 경고를 표시하지 않기 위한 것입니다. 이것은 선택 사항입니다 :) 오른쪽 창은 우리가 spring-context 모듈만 연결했지만 spring-core, spring-beans, spring-aop 및 spring-expression 모듈을 자동으로 가져왔음을 분명히 보여줍니다. pom.xml 파일의 명시적 버전을 사용하여 각 모듈에 대한 종속성을 작성하여 각 모듈을 개별적으로 연결할 수 있었지만 지금은 있는 그대로 만족합니다. 이제 패키지를 생성 하고 entities그 안에 , Cat, 3개의 클래스를 생성합니다 . 각 동물에게 이름(DogParrotprivate String name— 거기에서 일부 값을 하드코딩할 수 있습니다). 게터/세터는 공개됩니다. Main이제 클래스와 메서드 로 이동 main()하고 다음과 같이 작성합니다.

public static void main(String[] args) {
	// Create an empty Spring context that will look for its own beans based on the annotations in the specified package
	ApplicationContext context = 
		new AnnotationConfigApplicationContext("en.codegym.info.fatfaggy.animals.entities");

	Cat cat = context.getBean(Cat.class);
	Dog dog = (Dog) context.getBean("dog");
	Parrot parrot = context.getBean("parrot-polly", Parrot.class);

	System.out.println(cat.getName());
	System.out.println(dog.getName());
	System.out.println(parrot.getName());
}
먼저 빈을 찾기 위해 어떤 패키지를 찾아야 하는지 생성자에게 알리는 컨텍스트 객체를 만듭니다. 즉, Spring은 이 패키지를 살펴보고 빈임을 나타내는 특수 주석이 표시된 클래스를 찾으려고 시도합니다. 그런 다음 이러한 클래스의 개체를 만들어 컨텍스트에 넣습니다. 그런 다음 이 컨텍스트에서 고양이를 얻습니다. 우리는 컨텍스트 객체를 호출하여 우리가 원하는 객체의 클래스를 나타내는 bean(객체)을 제공합니다(그런데 클래스뿐만 아니라 인터페이스도 지정할 수 있습니다). 그런 다음 Spring은 요청된 클래스의 객체를 반환하고 변수에 저장합니다. 다음으로 Spring에 "dog"라는 빈을 가져오도록 요청합니다. Spring이 생성할 때Dog객체에 표준 이름을 부여합니다(생성된 빈에 명시적으로 이름이 지정되지 않은 경우). 이 이름은 클래스 이름이지만 첫 글자는 소문자입니다. 이 경우 우리 클래스는 이라고 부르 Dog므로 bean의 이름은 "dog"입니다. 그곳에 객체가 필요하다면 BufferedReaderSpring은 그것을 "bufferedReader"라고 명명할 것이다. 그리고 Java는 우리가 원하는 클래스를 100% 확신할 수 없기 때문에 개체를 반환한 Object다음 원하는 유형으로 수동 캐스팅합니다.Dog. 클래스가 명시적으로 표시된 옵션이 더 편리합니다. 세 번째 옵션은 클래스 이름과 빈 이름으로 빈을 가져오는 것입니다. 컨텍스트에 단일 클래스의 여러 bean이 있을 수 있습니다. 필요한 특정 빈을 나타내기 위해 이름을 나타냅니다. 여기서도 클래스를 명시적으로 나타내기 때문에 더 이상 캐스트를 수행할 필요가 없습니다. 중요한!Spring이 우리의 요구 사항과 일치하는 여러 bean을 찾으면 우리에게 제공할 bean을 결정할 수 없으므로 예외가 발생합니다. 따라서 이러한 상황을 피하려면 필요한 Bean을 Spring에 알리는 데 가능한 한 구체적이어야 합니다. Spring이 컨텍스트를 검색하고 요구 사항과 일치하는 단일 빈을 찾는 데 실패하면 예외도 발생합니다. 마지막으로 동물의 이름을 표시하여 필요한 개체를 실제로 얻었는지 확인합니다. 그러나 지금 프로그램을 실행하면 Spring이 불행하다는 것을 알게 될 것입니다. 컨텍스트에서 필요한 동물을 찾을 수 없습니다. 이것은 이러한 bean을 생성하지 않았기 때문입니다. 이전에 말했듯이 Spring은 클래스를 스캔할 때 자체 Spring 주석을 찾습니다. 그리고 Spring이 이러한 주석을 찾지 못하면 이러한 클래스가 생성해야 하는 bean에 해당한다고 생각하지 마십시오. 이 문제를 해결하려면 단순히@Component각 동물 클래스 앞에 주석을 추가합니다.

@Component
public class Cat {
	private String name = "Oscar";
	...
}
하지만 더 있습니다. 이 클래스의 bean이 특정 이름을 가져야 한다고 Spring에 명시적으로 알려야 하는 경우 주석 뒤에 괄호 안에 이름을 표시합니다. 예를 들어, parrot-polly메서드에서 이 앵무새를 가져오는 데 사용할 이름인 앵무새 빈에 " "라는 이름을 지정하도록 Spring에 지시 main하려면 다음과 같이 해야 합니다.

@Component("parrot-polly")
public class Parrot {
	private String name = "Polly";
	...
}
이것이 자동 구성 의 요점입니다 . 클래스를 작성하고 필요한 주석으로 표시하고 클래스가 있는 패키지를 Spring에 알립니다. 이것은 주석을 찾고 이러한 클래스의 객체를 생성하기 위해 프레임워크가 실행할 패키지입니다. 그런데 Spring은 @Component어노테이션뿐만 아니라 이 어노테이션을 상속하는 다른 모든 어노테이션도 찾습니다. 예를 들어 , @Controller, @RestController, @Service@Repository은 향후 기사에서 소개할 것입니다. 이제 Java 기반 구성을 사용하여 동일한 작업을 수행하려고 합니다 . 시작하려면@Component우리 수업의 주석. 더 어려운 점은 우리가 이러한 클래스를 작성하지 않았기 때문에 쉽게 수정할 수 없다는 것입니다. 즉, 주석을 추가할 수 없습니다. 이러한 클래스가 일부 라이브러리에 패키지된 것과 같습니다. 이 경우 Spring에서 인식하도록 이러한 클래스를 편집할 방법이 없습니다. 그러나 우리는 이러한 클래스의 객체가 필요합니다! 여기에서 개체를 생성하려면 Java 기반 구성이 필요합니다. 시작하려면 와 같은 이름으로 패키지를 만듭니다 configs. 이 패키지에서 와 같은 일반 Java 클래스를 만들고 MyConfig주석으로 표시합니다 @Configuration.

@Configuration
public class MyConfig {
}
main()이제 메서드를 수정하여 컨텍스트를 만드는 방법을 변경 해야 합니다 . 구성이 있는 클래스를 명시적으로 표시할 수 있습니다.

ApplicationContext context =
	new AnnotationConfigApplicationContext(MyConfig.class);
빈을 생성하는 여러 클래스가 있고 그 중 여러 클래스를 동시에 연결하려는 경우 쉼표로 구분하여 모두 표시하면 됩니다.

ApplicationContext context =
	new AnnotationConfigApplicationContext(MyConfig.class, MyAnotherConfig.class);
그리고 그것들이 너무 많아서 그것들을 모두 동시에 연결하고 싶다면, 그것들이 포함된 패키지의 이름을 간단히 표시하면 됩니다:

ApplicationContext context =
	new AnnotationConfigApplicationContext("en.codegym.info.fatfaggy.animals.configs");
이 경우 Spring은 패키지를 살펴보고 @Configuration주석으로 표시된 모든 클래스를 찾습니다. 음, 그리고 구성이 여러 패키지로 나누어지는 정말 큰 프로그램이 있는 경우 구성을 포함하는 패키지 이름의 쉼표로 구분된 목록을 표시하기만 하면 됩니다.

ApplicationContext context =
	new AnnotationConfigApplicationContext("en.codegym.info.fatfaggy.animals.database.configs",
		"en.codegym.info.fatfaggy.animals.root.configs",
		"en.codegym.info.fatfaggy.animals.web.configs");
또는 그들 모두에게 공통적인 패키지 이름:

ApplicationContext context =
	new AnnotationConfigApplicationContext("en.codegym.info.fatfaggy.animals");
원하는 대로 할 수 있지만 구성이 있는 클래스를 나타내는 첫 번째 옵션이 우리 프로그램에 가장 적합할 것 같습니다. 컨텍스트를 생성할 때 Spring은 주석으로 표시된 클래스를 찾고 @Configuration이러한 클래스의 자체 객체를 생성합니다. 주석 으로 표시된 메소드를 호출하려고 시도합니다 @Bean. 이는 이러한 메소드가 Spring이 컨텍스트에 추가할 빈(객체)을 리턴한다는 것을 의미합니다. 이제 Java 기반 구성을 사용하여 클래스에서 고양이, 개 및 앵무새용 빈을 생성합니다. 이것은 매우 간단합니다.

@Bean
public Cat getCat() {
	return new Cat();
}
여기서 우리는 고양이를 수동으로 생성하고 Spring에 전달합니다. Spring은 컨텍스트에 개체를 보유합니다. 명시적으로 bean에 이름을 부여하지 않았기 때문에 Spring은 메서드 이름과 동일한 이름을 부여할 것입니다. 우리의 경우 고양이 콩은 " getCat"라고 불릴 것입니다. 그러나 메서드에서 cat bean을 가져오기 위해 이름이 아닌 클래스를 사용하기 때문에 mainbean의 이름은 중요하지 않습니다. 마찬가지로 Spring이 bean에 메서드 이름을 부여한다는 점을 염두에 두고 dog bean을 생성합니다. parrot bean의 이름을 명시적으로 지정하려면 주석 뒤에 괄호 안에 이름을 표시하기만 하면 됩니다 @Bean.

@Bean("parrot-polly")
public Object weNeedMoreParrots() {
	return new Parrot();
}
보시다시피 여기서 Object반환 유형을 지정하고 메서드에 임의의 이름을 지정했습니다. 여기에서 이름을 명시적으로 지정했기 때문에 이것은 bean의 이름에 영향을 미치지 않습니다. 그래도 다소 의미 있는 반환 값과 메서드 이름을 지정하는 것이 좋습니다. 1년 후에 프로젝트를 다시 열 때 자신에게 호의를 베푸는 것 외에 다른 이유가 없다면 이렇게 하십시오. :) 이제 다른 bean을 생성하기 위해 하나의 bean이 필요한 상황을 고려하십시오 . 예를 들어, 고양이 콩에 있는 고양이의 이름이 앵무새의 이름에 "-killer"라는 문자열을 더하기를 원한다고 가정합니다. 괜찮아요!

@Bean
public Cat getCat(Parrot parrot) {
	Cat cat = new Cat();
	cat.setName(parrot.getName() + "-killer");
	return cat;
}
여기서 Spring은 이 bean을 생성하기 위해 프레임워크가 이전에 생성된 parrot bean을 전달해야 함을 볼 것입니다. 따라서 필요한 메서드 호출 체인을 정렬합니다. 먼저 앵무새 생성 메서드가 호출된 다음 프레임워크가 새 앵무새를 고양이 생성 메서드에 전달합니다. 여기에서 종속성 주입이 작동합니다. Spring 자체가 필요한 parrot bean을 우리 메서드에 전달합니다. IDEA가 변수에 대해 화를 내면 parrotparrot 생성 메서드의 반환 유형을 에서 로 변경하는 것을 잊지 Object마십시오 Parrot. 또한 Java 기반 구성을 통해 모든 Java 코드를 절대적으로 실행할 수 있습니다.빈 생성 방법에서. 실제로 무엇이든 할 수 있습니다. 다른 보조 객체를 생성하고, 다른 메서드를 호출하고, Spring 주석으로 표시되지 않은 메서드를 호출하고, 루프를 생성하고, 부울 조건을 생성하고, 마음에 떠오르는 것은 무엇이든 할 수 있습니다! 이는 자동 구성의 경우 모두 가능하지 않으며 XML 구성의 경우에는 더 적습니다. 이제 좀 더 재미있는 문제를 생각해 봅시다. 다형성과 인터페이스 :) 우리는 WeekDay인터페이스를 만들고 이 인터페이스를 구현하는 7개의 클래스를 만들 것입니다: Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday. String getWeekDayName()해당 클래스의 요일 이름을 반환하는 메서드를 인터페이스에 제공합니다 . 즉, Monday클래스는 "Monday" 등. 애플리케이션을 시작할 때 우리의 작업이 현재 요일에 해당하는 빈을 컨텍스트에 넣는 것이라고 가정합니다. 인터페이스를 구현하는 모든 클래스의 빈이 아니라 필요한 WeekDay빈 하나만 있으면 됩니다. 당신은 할 수 있습니다. 다음과 같이 하십시오.

@Bean
public WeekDay getDay() {
	DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();
	switch (dayOfWeek) {
		case MONDAY: return new Monday();
		case TUESDAY: return new Tuesday();
		case WEDNESDAY: return new Wednesday();
		case THURSDAY: return new Thursday();
		case FRIDAY: return new Friday();
		case SATURDAY: return new Saturday();
		default: return new Sunday();
	}
}
여기서 반환 유형은 인터페이스입니다. 이 메서드는 현재 요일에 따라 인터페이스를 구현하는 클래스 중 하나의 진정한 개체를 반환합니다. 이제 메서드에서 다음을 수행할 수 있습니다 main().

WeekDay weekDay = context.getBean(WeekDay.class);
System.out.println("Today is " + weekDay.getWeekDayName() + "!");
나에게 프로그램은 일요일이라고 알려줍니다 :) 내일 프로그램을 실행하면 컨텍스트에 완전히 다른 개체가 포함될 것이라고 확신합니다. 단순히 interface: 를 사용하여 bean을 가져오고 있음에 유의하십시오 context.getBean(WeekDay.class). Spring은 인터페이스를 구현하는 bean에 대한 컨텍스트를 검색하고 반환합니다. WeekDay그런 다음 변수가 Sunday 개체로 끝나고 이 변수를 사용하여 작업할 때 친숙한 다형성 개념이 적용된다는 것이 밝혀졌습니다 . :) 이제 일부 bean은 Spring에 의해 자동으로 생성되고 일부는 주석이 있는 클래스에 대한 패키지를 스캔하여 일부는 Java 기반 구성에 의해 생성되는 결합된 접근 방식 에 대한 몇 마디입니다 . @Component이를 고려하여 원래 버전으로 돌아가겠습니다. 여기서 Cat, DogParrot클래스는 주석으로 표시되었습니다 @Component. Spring이 자동으로 패키지를 스캔하도록 하여 동물을 위한 빈을 생성하고 싶지만 entities방금 했던 것처럼 요일을 포함하는 빈도 생성하고 싶다고 가정합니다. @ComponentScan클래스 수준에서 주석을 추가하기만 하면 됩니다 MyConfig. 이 주석은 에서 컨텍스트를 생성할 때 표시 main()하고 스캔해야 하는 패키지를 괄호 안에 표시하고 필요한 클래스의 빈을 자동으로 생성합니다.

@Configuration
@ComponentScan("en.codegym.info.fatfaggy.animals.entities")
public class MyConfig {
	@Bean
	public WeekDay getDay() {
		DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();
		switch (dayOfWeek) {
			case MONDAY: return new Monday();
			case TUESDAY: return new Tuesday();
			case WEDNESDAY: return new Wednesday();
			case THURSDAY: return new Thursday();
			case FRIDAY: return new Friday();
			case SATURDAY: return new Saturday();
			default: return new Sunday();
		}
	}
}
컨텍스트를 생성할 때 Spring은 클래스를 처리해야 함을 확인합니다 MyConfig. 클래스에 들어가 " en.codegym.info.fatfaggy.animals.entities" 패키지를 스캔하고 해당 클래스의 빈을 생성해야 하는 것을 확인한 다음 MyConfig클래스의 getDay()메서드를 실행하고 WeekDay컨텍스트에 빈을 추가합니다. 메서드 에서 main()우리는 이제 우리가 필요로 하는 모든 bean에 접근할 수 있습니다: 동물 개체와 요일이 있는 bean 모두. Spring이 일부 XML 구성 파일도 선택하도록 해야 하는 경우 설명을 찾기 위해 자체 웹 검색을 수행할 수 있습니다. :) 요약:
  • 자동 구성 사용 시도
  • 자동 구성 중에 Bean을 생성해야 하는 클래스가 포함된 패키지의 이름을 나타냅니다.
  • @Component이러한 클래스는 주석 으로 표시됩니다.
  • Spring은 이러한 모든 클래스를 실행하고 개체를 생성하고 컨텍스트에 넣습니다.
  • 어떤 이유로 자동 구성이 적합하지 않은 경우 Java 기반 구성을 사용합니다.
  • 이 경우 메서드가 필요한 개체를 반환하는 일반 Java 클래스를 만듭니다. @Configuration컨텍스트를 생성할 때 구성이 있는 특정 클래스를 나타내지 않고 전체 패키지를 스캔하려는 경우 이 클래스를 주석으로 표시합니다.
  • Bean을 리턴하는 이 클래스의 메소드는 주석으로 표시됩니다 @Bean.
  • Java 기반 구성을 사용할 때 자동 스캔을 활성화하려면 @ComponentScan주석을 사용합니다.
이 기사가 완전히 혼란스럽다면 며칠 후에 읽어보십시오. 또는 CodeGym의 초기 수준 중 하나에 있다면 Spring을 공부하기에는 조금 이른 시점일 수 있습니다. 나중에 Java 프로그래밍 기술에 자신감이 생기면 언제든지 이 기사로 돌아올 수 있습니다. 모든 것이 명확하다면, 당신은 당신의 애완 프로젝트를 Spring으로 변환하려고 시도할 수 있습니다. 어디선가 말도 안 되는 글을 썼다 :) 다음 기사에서 우리는 갑자기 spring-web-mvc 에 뛰어들어 Spring을 사용하여 간단한 웹 애플리케이션을 만들 것이다.
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION