Spring

김창모·2023년 5월 26일
0

Spring

목록 보기
1/1

JavaScript 를 사용할때 처음 접한 프레임워크는 React 였다.
Java 를 시작하며 백엔드 개발자를 꿈꾸게 되었고 Java 의 유명한 프레임워크는 Spring 이다.

왜 Spring (봄) 이냐 ?

Spring 이전에 Enterprise Java Bean 이라는 것을 사용했다고 한다.
Spring 이 EJB 의 단점을 보완하여 나왔고 더 널리 사용되므로 EJB 에 대해서 깊게 공부해보진 않았지만 EJB 는 사용성 보다는 이론에 집중하여 복잡하고 느렸다고 한다.
EJB 를 사용하며 불편함을 느낀 로드 존슨 , 위겐 휠러 , 얀 캬로프 세명이 오픈소스 프로젝트를 만들게 되었고 EJB 라는 겨울을 넘어 새로운 시작 이라는 뜻에서 Spring 이라고 이름지었다고 한다.

Spring 이란 무엇인가 ?

Java 언어의 웹 프레임워크로 Java 를 더 편리하게 사용하게 해주는 오픈소스 프레임워크이다.

프레임 워크(FrameWork) 란 ?

자주 쓰일만한 기능들을 한데 모아놓은 유틸들의 모음 이다. 기본적인 설계나 필요한 라이브러리는 알아서 제공해줄테니 개발자는 만들고 싶은 기능 구현에 집중할수 있게 도와준다.

Spring 의 특징

1. DI (의존성 주입)

애플리케이션의 구성 요소의 의존 관계가 소스코드 내부가 아닌 외부의 설정 파일을 통해 정의되는 방식이다.

의존성 주입 방법

- 생성자를 이용한 방법

생성자 주입은 생성자 호출 시점에 1회 호출되는것이 보장된다. 그렇기 때문에 주입받은 객체가 변하지 않거나 반드시 객체의 주입이 필요한 경우에 강제하기 위해 사용할수 있다. 가장 추천하는 의존성 주입 방법이며 생성자가 1개만 있을경우에 @Autowired 어노테이션을 생략해도 주입 가능하다.

- 메소드 ( setter ) 를 이용한 방법

필드값을 변경하는 Setter 메서드를 사용하여 의존 관계를 주입하는 방법이며 주입받는 객체가 변경될 가능성이 있는 경우 사용되며 추천되는 방법은 아니다.

- 필드 주입

필드에 바로 의존관계를 주입하는 방법이다.필드 주입을 이용하면 코드가 간결해지는 장점이 있지만 외부에서 접근이 불가능 하다는 단점이 존재하여 테스트 코드 작성시 문제가 되어 잘 사용하지 않는다.

생성자 주입을 사용해야 하는 이유

  1. 객체의 불변성 확보
  2. 테스트 코드의 작성
  3. final 키워드 작성 및 Lombok 과의 결합
  4. 순환 참조 에러 방지

2. IOC (제어 역전)

객체의 생성부터 소멸까지 개발자가 아닌 스프링 컨테이너가 대신 생명주기를 관리하는것이다.

3. AOP (관점 지향 프로그래밍)

어떤 로직을 기준으로 핵심적인 관점 , 부가적인 관점 으로 나누고 그 관점을 기준으로 모듈화 하는것을 말한다.

Spring 의 기능

  1. Spring JDBC
  2. Spring MVC
  3. Spring Security
  4. Spring AOP
  5. Spring ORM
  6. Spring Test

Spring Container

스프링 컨테이너는 스프링에서 자바 객체들을 관리하는 공간입니다. 자바 객체들은 스프링 컨테이너에 빈으로 등록되며 이 빈의 생명주기를 개발자 대신 스프링 컨테이너가 관리한다.
스프링 컨테이너에 빈을 등록하는 이유는 스프링이 각 객체간의 의존관계를 관리하도록 하기 위함이다.
객체가 의존관계를 등록할 때 스프링 컨테이너는 해당 빈을 찾고 의존성을 만든다.
이때 스프링 빈은 싱글톤 패턴으로 관리되며 빈으로 등록하는 방법은 아래 두가지가 있다.

Spring Bean 은 Spring Container 에서 관리
Spring Bean 은 싱글톤

Bean 등록 방법

Bean 등록 방법

  • 컴포넌트 스캔
  • 스프링 빈 직접 등록

컴포넌트 스캔

컴포넌트 스캔을 이용하는 방법은 @ComponentScan 어노테이션을 main 메서드를 가진 클래스에 등록해주고 등록할 컴포넌트에 @Component 어노테이션을 붙여준다.

package com.hello.hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class HelloApplication {

	public static void main(String[] args) {
		SpringApplication.run(HelloApplication.class, args);
	}

}

현재 우리 프로젝트에서 @SpringBootApplication 을 살펴보면

/*
 * Copyright 2012-2023 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot.autoconfigure;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.context.TypeExcludeFilter;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.annotation.AliasFor;
import org.springframework.data.repository.Repository;

/**
 * Indicates a {@link Configuration configuration} class that declares one or more
 * {@link Bean @Bean} methods and also triggers {@link EnableAutoConfiguration
 * auto-configuration} and {@link ComponentScan component scanning}. This is a convenience
 * annotation that is equivalent to declaring {@code @SpringBootConfiguration},
 * {@code @EnableAutoConfiguration} and {@code @ComponentScan}.
 *
 * @author Phillip Webb
 * @author Stephane Nicoll
 * @author Andy Wilkinson
 * @since 1.2.0
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

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

	/**
	 * Exclude specific auto-configuration class names such that they will never be
	 * applied.
	 * @return the class names to exclude
	 * @since 1.3.0
	 */
	@AliasFor(annotation = EnableAutoConfiguration.class)
	String[] excludeName() default {};

	/**
	 * Base packages to scan for annotated components. Use {@link #scanBasePackageClasses}
	 * for a type-safe alternative to String-based package names.
	 * <p>
	 * <strong>Note:</strong> this setting is an alias for
	 * {@link ComponentScan @ComponentScan} only. It has no effect on {@code @Entity}
	 * scanning or Spring Data {@link Repository} scanning. For those you should add
	 * {@link org.springframework.boot.autoconfigure.domain.EntityScan @EntityScan} and
	 * {@code @Enable...Repositories} annotations.
	 * @return base packages to scan
	 * @since 1.3.0
	 */
	@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
	String[] scanBasePackages() default {};

	/**
	 * Type-safe alternative to {@link #scanBasePackages} for specifying the packages to
	 * scan for annotated components. The package of each class specified will be scanned.
	 * <p>
	 * Consider creating a special no-op marker class or interface in each package that
	 * serves no purpose other than being referenced by this attribute.
	 * <p>
	 * <strong>Note:</strong> this setting is an alias for
	 * {@link ComponentScan @ComponentScan} only. It has no effect on {@code @Entity}
	 * scanning or Spring Data {@link Repository} scanning. For those you should add
	 * {@link org.springframework.boot.autoconfigure.domain.EntityScan @EntityScan} and
	 * {@code @Enable...Repositories} annotations.
	 * @return base packages to scan
	 * @since 1.3.0
	 */
	@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
	Class<?>[] scanBasePackageClasses() default {};

	/**
	 * The {@link BeanNameGenerator} class to be used for naming detected components
	 * within the Spring container.
	 * <p>
	 * The default value of the {@link BeanNameGenerator} interface itself indicates that
	 * the scanner used to process this {@code @SpringBootApplication} annotation should
	 * use its inherited bean name generator, e.g. the default
	 * {@link AnnotationBeanNameGenerator} or any custom instance supplied to the
	 * application context at bootstrap time.
	 * @return {@link BeanNameGenerator} to use
	 * @see SpringApplication#setBeanNameGenerator(BeanNameGenerator)
	 * @since 2.3.0
	 */
	@AliasFor(annotation = ComponentScan.class, attribute = "nameGenerator")
	Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

	/**
	 * Specify whether {@link Bean @Bean} methods should get proxied in order to enforce
	 * bean lifecycle behavior, e.g. to return shared singleton bean instances even in
	 * case of direct {@code @Bean} method calls in user code. This feature requires
	 * method interception, implemented through a runtime-generated CGLIB subclass which
	 * comes with limitations such as the configuration class and its methods not being
	 * allowed to declare {@code final}.
	 * <p>
	 * The default is {@code true}, allowing for 'inter-bean references' within the
	 * configuration class as well as for external calls to this configuration's
	 * {@code @Bean} methods, e.g. from another configuration class. If this is not needed
	 * since each of this particular configuration's {@code @Bean} methods is
	 * self-contained and designed as a plain factory method for container use, switch
	 * this flag to {@code false} in order to avoid CGLIB subclass processing.
	 * <p>
	 * Turning off bean method interception effectively processes {@code @Bean} methods
	 * individually like when declared on non-{@code @Configuration} classes, a.k.a.
	 * "@Bean Lite Mode" (see {@link Bean @Bean's javadoc}). It is therefore behaviorally
	 * equivalent to removing the {@code @Configuration} stereotype.
	 * @since 2.2
	 * @return whether to proxy {@code @Bean} methods
	 */
	@AliasFor(annotation = Configuration.class)
	boolean proxyBeanMethods() default true;

}

@ComponentScan 어노테이션이 @SpringBootApplication 내에 포함된것을 알수 있다.

0개의 댓글