java파일을 이용하여 bean객체를 만들고 주입하며, 자동주입은 어떻게 하는지 알아보도록 하자.

 

 

 

일단 기본적으로 예제에 사용할 TestBean7을 위와 같이 정의하였다.

 

 

 

 

 

 

1. 생성자를 이용한 주입

 

 

위와 같이 설정해주면 된다. 뭔가 간단한거 같다....

그냥 원래 자바파일에서 생성자에 매개변수 넣어주듯이 하면 된다. 

생성자의 매개변수를 한개씩 사용자가 넣어주는 예제이지만 FileStream하여 파일에서 읽어올 수도 있겠고, 웹이라면 Request하여 읽어올 수도 있을것 같다!!

 

 

 

이렇게 하면 정상적으로 출력된다. 

 

 

 

 

 

 

 

 

2. setter를 이용한 주입

 

 

 

이것도 뭐 간단하다.

너무도 당연하게 setter에 직접 데이터를 넣어주는 방식이다. 변수를 여러가지로 활용할 수 있겠다.

main의 출력코드는 생략하겠다.

 

 

 

 

 

 

 

 

3. 자동주입

    3-1. Autowire.BY_NAME

 

 

TestBean8은 DataBean2 타입인 data1과 data2 2개가 있다.

 

 

 

이름으로 객체를 찾아서 자동으로 주입해주는 것은 java파일에서는 위와 같이 설정한다.

DataBean2 형의 필드와 이름이 똑같은 data1과 data2를 bean으로 등록해준다.

 

TestBean8 타입의 di3을 정의해주는데 @Bean(autowire = Autowire.BY_NAME) 어노테이션으로 설정하여 이름으로 객체를 자동주입할 수 있도록 해준다.

 

 

 

 

결과는 아주 잘 나온다..

 

 

 

 

 

 

 

 

 

    3-2. Autowire.BY_TYPE

 

 

type이 같은 빈을 찾아서 자동으로 주입해주는 어노테이션 설정이다. 어짜피 타입으로 찾기때문에 메소드의 이름은 중요하지 않을것이다. data100이라고 그냥 대충 정해봤다.

 

그후 di4를 정의하는데 @Bean(autowire = Autowire.BY_TYPE) 어노테이션을 이용하여 타입으로 객체를 찾아 자동주입하도록 설정하였다.

 

 

 

 

잘 나오는 것을 확인하였다.

'JAVA > Spring' 카테고리의 다른 글

JSR-250 어노테이션  (0) 2020.04.11
Annotation을 이용한 빈 설정  (0) 2020.04.11
Java코드를 활용한 Bean 등록  (0) 2020.04.10
자동 주입  (0) 2020.04.10
컬렉션 주입  (0) 2020.04.09

지금까지는 bean을 등록하기 위해서 beans.xml 이라는 xml파일을 계속해서 사용해왔다.

이는 spring버전의 발전에 따라 xml파일에서 뿐만 아니라 java코드에서 bean을 등록할 수도 있도록 바뀌었다.

(그리고, 이게 더 많이 쓰인다고 한다...)

 

지금까지 했던 bean등록의 여러가지 방법을 java파일에서는 어떻게 활용하면 되는지 알아보자!!

 

 

 

 

 

 

 

 

1. java파일을 bean등록파일로 만들기

   (@Configration , @Bean)

 

 

java 파일에서 bean을 등록하기 위해서는 @Configration이라는 어노테이션을 클래스에 붙여준다.

그리고 xml파일에서 bean태그를 이용하여 빈을 등록해 주었듯이 @Bean 어노테이션을 이용하여 메소드로써 정의해주면 된다.

 

 

 

TestBean6 라는 클래스가 정의되어 있다고 치자.

 

 

 

위와 같이 빈 등록 파일을 JavaBean이라는 자바파일로 만들었다.

java1이라는 메소드를 @Bean 어노테이션을 이용하여 정의하였는데 bean의 id값이 바로 메소드의 이름이 된다.

xml파일과 동일하게 다른 설정을 해주지 않으면 default값은 singleton이다.

 

 

 

 

 

main도 조금 달라졌다.

ClassPathXmlApplicationContext를 사용하여 xml을 불러왔었는데, 자바를 사용할때는 

AnnotationConfigApplicationContext를 사용하여 자바클래스를 불러온다. xml파일은 해당파일의 path를 다 적어주어야 하지만 자바클래스는 위와같이 JavaBean.class와 같이 적어주면 된다.

 

 

 

 

 

 

 

 

2. Bean의 이름 설정해주기

   (@Bean(name="빈 이름"))

 

 

위에서 bean의 id값은 메소드의 이름이라고 설명하였다. 메소드의 이름을 건드리지 않고 빈의 이름을 설정하는 방법이 있다.

 

 

 

위와 같이 빈의 name속성을 바꾸어주면 메소드의 이름을 바꾸지 않고 손쉽게 빈의 이름을 변경할 수 있다.

 

 

 

 

 

 

 

 

 

3. 여러가지 bean 설정들

   (@Lazy, @Scope("singleton/prototype"), @Primary)

 

 

xml에서 사용했던 설정들을 java파일에서도 그대로 다 사용할 수 있다. 모두 어노테이션을 이용하여 설정한다.

 

 

 

@Lazy 어노테이션은 xml의 lazy-init 속성과 같다. @Lazy를 설정하면 lazy-init이 true값이 되며, getBean을 해야 객체를 생성한다.

 

@Scope("prototype") 어노테이션은 안써주면 default값은 singleton이다. @Scope("prototype")을 써줌으로써 getBean으로 객체를 새로 생성할 때마다 서로 다른 객체가 생성된다.

 

@Primary 어노테이션은 bean의 id가 설정되어 있지 않을 때 사용한다. 같은 type의 빈이 여러개 설정되어 있을 때, @Primary 어노테이션이 설정되어 있는 bean이 우선으로 불러와진다.

 

 

 

 

 

 

 

 

 

4. init, destroy 메소드 설정하기

   (@Bean(initMethod="init메소드", destroyMethod="destroy메소드"))

 

 

xml에서는 init메소드나 destroy메소드를 사용하기 위해서는

intit-method="init메소드" 이나 destroy-method="destroy메소드" 를 사용하였다. java도 비슷하다.

@Bean 어노테이션에 설정에 @Bean(initMethod="init메소드", destroyMethod="destroy메소드") 와 같이 설정해주면 된다.

 

 

 

TestBean6 클래스에 다음과 같이 init이라는 메소드와 destroy라는 메소드를 정의하였다.

 

 

 

자바 빈 설정파일에 java2라는 메소드를 정의하였으며 @Bean 어노테이션의 속성을 위와 같이 설정하여 init메소드와 destroy메소드를 설정하였다. 

 

 

 

 

main에서 돌리면 다음과 같이 bean객체가 생성되기 전과 후에 각각 init메소드와 destroy메소드가 정상적으로 호출된 것을 볼 수 있었다.

'JAVA > Spring' 카테고리의 다른 글

Annotation을 이용한 빈 설정  (0) 2020.04.11
Java를 이용한 Bean 객체 주입  (0) 2020.04.10
자동 주입  (0) 2020.04.10
컬렉션 주입  (0) 2020.04.09
의존성 주입 (Dependency Injection)  (0) 2020.04.09

지금까지는 xml을 이용해서 생성자, setter를 사용한 주입을 알아보았다.

빈 객체를 한개한개씩 아이디 지정하여 넣어주지 않아도 자동으로 주입할 수 있는 자동 주입에 대해서 알아보겠다.

 

자동주입은 기본 자료형에서는 동작하지 않고, 사용자 지정 객체타입에서만 동작한다.

특정클래스를 가지고 만든 객체의 주소값을 담는 참조변수같은 경우 자동으로 주입 가능하는 뜻이다!!

 

 

 

 

1. 이름을 통한 주입

 

이름을 통한 주입을 하기위해서는 bean태그의 속성에 autowire="byName" 를 추가해 주면 된다. 어떤식으로 사용해야 자동으로 주입을 해주는지 코드를 살펴보자.

 

 

 

 

다음과 같이 TestBean4라는 이름의 클래스를 정의하였다.

 

 

id가 data1, data2인 빈을 정의한 후, autowire="byName" 이라는 속성을 넣어주면 이름으로 빈을 찾아서 자동으로 TestBean4의 data1, data2에 각각 주입을 해준다. 

 

 

 

실행하면 정상적으로 출력되는 모습을 볼 수 있었다.

 

 

 

 

 

 

 

2. 타입을 통한 주입

 

타입을 통한 주입을 하기위해서는 bean태그의 속성에 autowire="byType" 를 추가해 주면 된다.

 

 

 

다음과 같이 TestBean5를 정의하였다.

 

 

 

클래스 타입으로 찾을 것이기 때문에 굳이 id를 설정해주지 않았다.

DataBean2 타입으로 만들어진 bean이 있고, auto2에 autowire="byType"하였기 때문에 빈의 타입으로 알아서 자동주입된다.

 

 

 

실행하면 정상적으로 출력되는 모습을 볼 수 있었다.

'JAVA > Spring' 카테고리의 다른 글

Java를 이용한 Bean 객체 주입  (0) 2020.04.10
Java코드를 활용한 Bean 등록  (0) 2020.04.10
컬렉션 주입  (0) 2020.04.09
의존성 주입 (Dependency Injection)  (0) 2020.04.09
Bean 객체의 생성시점과 생명주기  (0) 2020.04.08

자바의 컬렉션 중에서 List, Set, Map, Properties 4개의 타입은 어떻게 주입이 되는지 알아보겠다.

 

 

 

 

TestBean3라는 포조클래스에 위와 같이 필드를 선언하고 모든 필드에 대해서 getter, setter를 선언해주었다.

앞에 글에서 사용한 setter를 이용한 주입으로 자바 컬렉션 타입들에 주입을 시도해볼 것이다.

 

 

 

xml 파일에서 각각의 컬렉션타입의 setter주입을 할때, 이미 정의되어 있는 bean을 불러와서 사용할 때는 아래의 beans_data라는 이름의 bean을 공통적으로 사용하겠다.

 

 

 

 

 

 

 

 

1. List

 

 

bean1 이라는 빈 태그 안에 property 태그를 사용하여 setter주입을 시도한다.

List타입이기때문에 List태그 사용하고, 그 태그 안에 value태그를 이용하여 제네릭타입에 맞는 value값을 주입해준다.

 

최우선순위인 String형은 default의 느낌이라서 type정의를 안해주어도 상관없지만, 

int와 같은 다른 기본형들은 꼭 셋팅을 해주는 것이 좋다.

 

DataBean형인 List에 값을 넣는 "list3"의 경우,

주입할 bean을 직접 bean태그를 이용해서 넣어도 되고, ref bean을 이용하여 미리 정의되어 있는 beans_data를 넣어주어도 된다. beans_data는 prototype이므로 넣을 때마다 새로운 객체가 생성되겠다. 

 

 

 

다음과 같이 실행하면

 

 

이런결과를 얻을 수 있다.

 

 

 

 

 

 

 

2. Set

 

 

 

bean1 이라는 빈 태그 안에 property 태그를 사용하여 setter주입을 시도한다.

Set타입이기때문에 Set태그 사용하고, 그 태그 안에 value태그를 이용하여 제네릭타입에 맞는 value값을 주입해준다.

방법과 형태는 List와 똑같다.

 

 

Set은 중복된 값을 하나의 값으로 생각하여 한개만 넣는 특징이 있다.

그래서 위와 같이 여러개 같은 값을 찍어도, 

 

 

 

 

이렇게 한개만 출력된다.

<ref bean="beans_data" /> 를 두번찍었고, scope도 prototype이라서 다른 추가할 때마다 객체가 생성될것 같지만

id값이 동일한 bean이기 때문에 한개로 인식해서 한개만 출력한다.

 

 

 

 

 

 

 

3. Map

 

 

 

Map은 key와 value쌍으로 이루어져있는 형태이다. 

TestBean3클래스에 value는 Object형으로 선언하였기 때문에 어떤 형태의 값도 다 담을 수 있을 것이다.

 

map태그 안에 entry라는 태그를 사용하여 key값과 value값을 넣어준다.

value값이 String이 아닌 기본형일때는 위와같이 value-type이라는 속성으로 선언을 해주어야 한다.

 

새로운 bean 객체를 map에 집어 넣을 때에는 k3와 같이 하면 되고,

기존에 있는 bean을 넣을 때는 k4처럼 넣으면 된다. 

 

 

 

 

 

 

 

 

 

 

 

4. Properties

 

Properties는 문자열만 담을 수 있는 컬렉션이다.

 

 

 

props 태그 아래에 prop태그를 이용하여 key값과 그 안에 들어갈 value를 설정해준다.

Properties는 문자열 밖에 담을 수 없기 때문에 뭐 따로 value속성이나 이런게 존재하지는 않는것 같다. 저런 형식으로 넣어주면 된다.

 

'JAVA > Spring' 카테고리의 다른 글

Java코드를 활용한 Bean 등록  (0) 2020.04.10
자동 주입  (0) 2020.04.10
의존성 주입 (Dependency Injection)  (0) 2020.04.09
Bean 객체의 생성시점과 생명주기  (0) 2020.04.08
IoC 컨테이너  (0) 2020.04.07

DI (Dependency Injection) 이란?

 

bean객체를 생성할 때, bean객체가 관리할 값이나 객체를 주입하는 것을 의미한다.

만약 ,객체가 생성될 때 해당 객체가 관리할 변수의 값이 정해져 있으면 알아서 bean객체가 생성될 때 변수에 값이 들어간다.

 

 

 

 

+ 2021-12-10 추가

의존하는 객체를 직접 생성하는 것이 아니라, 외부에서 생성한 후 주입하는 것.

DI를 할 때 정적인 클래스 의존관계동적인 클래스 의존관계를 생각해보아야 한다.

 

- 정적인 클래스 의존관계 ? import코드만 보고 의존관계를 파악할 수 있는 것. 애플리케이션을 실행하지 않아도 의존관계가 파악이 가능하다.

ex) public Car car = new porsche(); 

Car가 인터페이스이고 porsche가 구현 클래스라면 이 코드만 보고도 런타임 이전에 의존관계를 파악할 수 있다. 그리고 외부에서 의존관계를 주입하는 것이 아닌 직접 생성을 하고 있다.

 

 

- 동적인 클래스 의존관계 ? 런타임(실행)시점에서 의존관계를 파악할 수 있는 것.

ex) public final Car car;

Car가 인터페이스 이면 이 코드만 보고는 Car의 구현객체를 알 수 없으며 런타임 이전에 의존관계를 파악할 수가 없다. (car변수에는 생성자주입과 같은 방식으로 외부에서 주입을 받는다.)

 

 

DI를 할 때에는 코드에서는 런타임(실행)시점의 의존관계가 드러나지 않아야 한다. 즉, 동적인 클래스 의존관계여야 하며 이는 인터페이스에만 의존하고 있어야 한다는 의미와 같다. (객체지향적 설계를 위해 OCP, DIP원칙을 지키는 것과도 상통하다.)

런타임(실행)시점에서 실제 구현 객체를 생성하고 클라이언트에 주입(전달)함으로써 외부에서 의존관계를 결정해야 한다. 이와 같은 조건이 맞을 때 DI가 되었다고 한다.

 

 

 

 

 

 

 

 

 

 

 

TestBean클래스에 다음과 같이 생성자가 정의되어있다. 

기본생성자, 정수형 변수를 받는 생성자, 실수형 변수를 받는 생성자 이렇게 3개이다.

 

 

 

 

 

(printData메소드는 필드의 값을 프린트해주는 함수)

 

자바에서는 이렇게 new를 이용하여 새로운 객체를 만들어가면서 그 객체의 생성자의 매개변수에 정수형 변수, 실수형 변수를 넣으면 해당 변수의 타입에 알맞는 생성자를 찾아서 인스턴스 변수가 생성되게 된다.

 

이 작업을 spring xml에서 하려고 하면 어떻게 해야할까??

 

 

 

 

bean객체를 정의하는 bean태그안의 속성에 constructor-arg라는 태그를 추가한다.

constructor-arg태그의 속성중 value에는 생성자의 매개변수에 들어갈 변수의 value값이 들어가고 type은 매개변수의 타입이다.

 

spring에서는 String > double > int 순서로 우선순위를 가진다. 그러므로 만약 type속성을 아무것도 지정해주지 않았는데, TestBean 클래스에 String형을 매개변수로 받는 생성자가 정의되어 있다면 value값은 자동으로 String으로 인식된다.

 

최우선순위가 String이므로 만약 type이 String이면 굳이 써주지 않아도 되지만..

쓰고 싶다면, java는 String이 클래스이기 때문에 그냥 type="string" 이 아닌, type="java.lang.String" 과 같이 써주어야 하겠다.

 

 

 

 

또한 , 위와 같이 xml에 bean을 정의하는데 생성자를 통해 주입할때 생성자 매개변수의 순서는 크게 상관이 없다.

먼소리냐고?

 

 

 

 

 

 

생성자중에 다음과 같이 int, double, String 순서로 매개변수를 받는 생성자가 존재한다고 치자.

 

만약 자바에서,

 

 

이런식으로 객체를 생성했다면? 당연히 오류가 난다. 저런 매개변수를 갖는 생성자를 찾을 수 없기 때문이다.

 

그런데.. spring bean을 정의하는 xml에서는

 

 

 

이런식으로 정의한후

 

ClassPathXmlApplicationContext ctx = new CalssPathXmlApplicationContext("com/study/spring/config/bean.xml");
TestBean2 test2 = ctx.getBean("obj6", TestBean2.calss);
test2.printData();

 

이와 같이 하여도 오류가 나지 않는다는 것이다.

 

 

spring에서는 먼저, 정의된 생성자의 순서대로 값을 주입할 수 있는 생성자를 찾는다
근데 없다? 그러면 이 값을 모두 주입할 수있는 생성자를 찾는다! 

위의 예가 순서대로 값을 주입할 수 있는 생성자가 없어서 이 값을 모두 주입할 수 있는 생성자를 찾은 예가 되겠다.

 

 

 

 

 

 

 

 

객체주입

 

말로만 '객체주입' 이렇게 써놓으면 먼소린가 싶다 나도..

코드로 보자.

 

 

 

DataBean이라는 이름의 POJO class가 있다고 가정하고,

beans_data라는 이름의 bean을 정의한다. 이 bean은 prototype이니까 불러올 때마다 객체를 새로 생성한다.

 

obj7이라는 bean을 정의할때 생성자의 매개변수로서 beans_data를 2개 집어 넣는다.

대충 TestBean2가 어떻게 생겨먹었는지 유추할수 있다.

 

 

 

 

DataBean type의 매개변수 2개를 생성자에서 받는 형태는 xml에서 저렇게 정의한다.

data1과 data2는 서로 다른 변수여야 하기때문에 beans_data라는 prototype의 bean을 따로 정의해서 그 bean을 ref속성을 이용하여 집어 넣는 방법이다.

 

 

 

 

 

 

 

 

 

 

setter를 이용한 주입

 

위에 예제에서 사용된 DataBean이라는 POJO 클래스가 getter, setter가 정의되어 있다고 가정해보자.

 

 

 

 

다음과 같이 property태그를 이용하여 setter주입을 할 수 있다.

 

name이 data1이니까 setData1을 자동으로 찾아가고, value의 값을 매개변수로 자동으로 넣어준다.

property의 name 맨 앞글자를 대문자로(D) 바꾸고 앞에 set을 붙여 setData1이라는 함수를 찾는 방식으로 setter를 찾는다고 한다... (정확하진 않으나.. 강의에서 그랬음...)

 


만약 setData1이름의 메소드가 매개변수만 다르게 여러개있으면 value는 String > double > int 우선순위 순서대로 들어감

'JAVA > Spring' 카테고리의 다른 글

자동 주입  (0) 2020.04.10
컬렉션 주입  (0) 2020.04.09
Bean 객체의 생성시점과 생명주기  (0) 2020.04.08
IoC 컨테이너  (0) 2020.04.07
Maven 설정  (0) 2020.04.07

xml 파일에 bean태그를 이용하여 bean을 직접 정의할 수 있다.

bean태그에는 bean객체의 생성시점과 생명주기를 직접 설정할 수 있는 속성들이 있다 한개한개 알아보자.

 

 

 

lazy-init

 

게으른..초기화..? 

이 속성을 true값으로 설정하면 xml을 로딩할 때 객체가 바로 생성되지 않고 getBean을 사용해야 객체가 생성된다.

 

 

 

<bean id="t1" class="com.study.spring.beans.TestBean" lazy-init="true"/>

 

 

// xml이 로딩됨. lazy-init속성이 true이면 이때 객체가 생성되지 않는다.
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("com/study/spring/config/beans.xml");
		
// getBean을 사용하여 bean을 블러옴. lazy-init속성이 true이면 이때 객체가 생성된다.
TestBean t1 = ctx.getBean("t1", TestBean.class);

 

 

 

 

 

 

 

scope

 

scope속성이 singleton이면 한번 생성된 객체가 다시 생성되지 않는다. (singleton이 default값이다.)

scope속성이 prototype이면 호출 될 때마다 객체를 생성할 수 있다.

 

 

 

<bean id="t1" class="com.study.spring.beans.TestBean" lazy-init="true" scope="prototype" />

 

 

 

lazy-init이 true이므로 getBean을 호출해야 객체가 생성되며, scope가 prototype이므로 getBean을 호출 할 때마다 다른 객체가 생성된다.

 

 

 

// xml이 로딩됨. lazy-init속성이 true이기 때문에 이때 객체가 생성되지 않는다.
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("com/study/spring/config/beans.xml");
		
// getBean을 사용하여 bean을 블러옴. lazy-init속성이 true이기 때문에 이때 객체가 생성된다.
TestBean t1 = ctx.getBean("t1", TestBean.class);

// getBean을 이용하여 동일한 bean인 "t1"을 호출하였지만 t1과 t2는 서로 다른 객체이다.
TestBean t2 = ctx.getBean("t1", TestBean.class);

 

 

 

 

 

 

 

init-method 와 destroy-method

 

init-method는 객체가 생성될 때 호출되는 메소드를 정의하는 속성이다.

destroy-method는 객체가 소멸될 때 호출되는 메소드이다. (ctx.close(); 하면 IoC컨테이너 내에 존재하던 모든 객체는 소멸된다.)

 

 

 

<bean id="t1" class="com.study.spring.beans.TestBean" lazy-init="true" init-method="beanInit" destroy-method="beanDestroy" />

 

 

 

 

TestBean 클래스에 beanInit 메소드와 beanDestroy 메소드가 사용자에 의해 각각 "init메소드", "destroy메소드" 라고 출력하도록 정의되었다고 가정한다. 위와 같이 bean을 정의 하였다면,

 

 

 

 

 

// xml이 로딩됨. lazy-init속성이 true이기 때문에 이때 객체가 생성되지 않는다.
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("com/study/spring/config/beans.xml");
		
// getBean을 사용하여 bean을 블러옴. lazy-init속성이 true이기 때문에 이때 객체가 생성된다.
// init-method가 정의되어 있으므로 이곳에서 호출된다.

TestBean t1 = ctx.getBean("t1", TestBean.class);
System.out.printf("%s :  t1객체입니다.\n", t1);

// destroy-method가 정의되어 있으므로 이곳에서 호출된다.

 

 

 

 

출력결과는

 

init메소드

com.study.spring.beans.TestBean@12345 :  t1객체입니다.

destroy메소드

 

이렇게 될것이다!!

 

 

 

 

 

 

 

default-init-method 와 default-destroy-method

 

bean태그에 속성으로 정의했던 init-method와 destroy-method와는 달리 상위태그인 beans태그의 속성으로 지정된다.

만약 bean태그에 속성으로 init-method나 destroy-method가 정의되어 있지 않다면 default-init-method 나 default-destroy-method가 호출이 된다.

 

만약에 default-init-method 와 default-destroy-method, init-method와 destroy-method가 모두 정의되어 있다면????

default는 무시되고 bean에 지정되어 있는 메소드가 호출된다.

 

 

 

 

default-init-method 와 default-destroy-method 속성이 사용되고 있으나, 속성값으로 정의된 메소드가 정의되어 있지 않다면 .. 오류가 나지 않는다. 

하지만, init-method와 destroy-method는 속성이 사용되고 있으나, 속성값으로 정의된 메소드가 정의되어 있지 않다면???? 오류난다.

 

즉, 메소드가 없을 경우

default-init-method 와 default-destroy-method -> 아무일도 일어나지 않음

init-method와 destroy-method -> 오류남.

 

 

 

 

 

 

 

 

BeanPostProcessor

 

BeanPostProcessor는 인터페이스이며 postProcessBeforeInitialization, postProcessAfterInitialization 라는 메소드를 정의하고있다.

postProcessBeforeInitialization는 init메소드가 호출되기 전에 먼저 호출되는 함수이다.

postProcessAfterInitialization는 intit메소드가 호출 된 후에 호출되는 함수이다. 

즉, init메소드 호출 전 후로 가로채기 하는 메소드이다!

 

 

 

//init 메서드 호출 전
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
	// TODO Auto-generated method stub
	System.out.println("before");
	return bean;
}

	
//init 메서드 호출 후
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
	// TODO Auto-generated method stub
	System.out.println("after");
	return bean;
}

 

 

구현 클래스이기 때문에 Override를 해준것이고, 반환값은 Object 형인 bean이다. 

bean객체마다 다음 메소드들을 활용하려면 String형 beanName매개변수를 사용하여 bean객체의 id값을 이용하여 함수를 활용하면 되겠다.

'JAVA > Spring' 카테고리의 다른 글

컬렉션 주입  (0) 2020.04.09
의존성 주입 (Dependency Injection)  (0) 2020.04.09
IoC 컨테이너  (0) 2020.04.07
Maven 설정  (0) 2020.04.07
스프링 MVC 프레임워크의 구조  (0) 2020.03.31

IoC (Inversion Of Control) : 제어역전

 

 

어떠한 제어권을 역전한다는 이야기냐...?

 

어떠한 객체를 생성하거나, 그 객체를 셋팅하거나, 객체를 활용하여 작업을 한다거나 ..

이 모든것은 개발자가 해왔다. spring을 사용해본적이 없는 나는 이게 아주 당연하다고 생각했다.

 

그런데

 

IoC는 개발자가 몇가지 셋팅만으로 전체 프로그램을 제어하는 제어권을 프레임워크가 가지는 것을 의미한다.

개발을 하다보면 반복되는 작업이 많은데 그런것을 프레임워크에 미리 구현을 해둔것.

'개발자는 어떠한 클래스를 이용해서 객체를 만들것이다' 와 같은 프레임워크가 판단할수 없는 것만 설정해주면 된다!

 

 

 

 

 

 

+ 2021-12-10 내용추가

 

스프링 핵심원리를 다시 공부하다가 보니까 설명을 너무 간단하게 한 것 같아서 추가해본다.

 

개발자의 입장에서 봤을 때 객체를 생성하고, 연결하고, 실행하는 흐름이 자연스러운 흐름이다. 우리가 예를 들어 스프링에서 AppConfig(DI컨테이너)처럼 구성을 담당하는 클래스를 사용함으로써 클라이언트가 직접 객체를 생성하고 연결, 실행하는 흐름이 아닌 AppConfig에서 인터페이스의 구현클래스를 설정하고 객체를 생성한다. 프로그램에 대한 제어의 흐름은  AppConfig가 모두 가지고 있는 것이며 인터페스들의 구현클래스는 그 역할에 대한 구현을 수행하는 로직만을 실행하게 된다. 

이처럼 개발자가 흐름을 제어하는 것이 아니라 외부에서 흐름의 제어권을 가지게 되는 것을 제어의 역전이라고 한다.

 

 

 

 

 

 

프레임워크와 라이브러리

 

이 둘의 차이점은 무엇일까?

예를 들어, JUnit과 같은 프레임워크는 내가 작성한 코드를 제어하고 어떤 내부적인 로직을 통해서 코드를 대신 실행해주기 때문에 프레임워크가 맞다.

그러나 jQuery와 같은 라이브러리는 내가 코드를 작성하면서 필요할 때 사용함으로써 제어의 흐름을 내가 담당하기 때문에 프레임워크가 아니라 라이브러리이다.

 

 

 

 

 

 

POJO Class (Plain Old Java Object)

 

 

들어는 봤는데 명확하지 않았던 용어.

 

자바모델이나 기능, 프레임워크 등에 따르지 않고 홀로 독립적으로 단순한 기능만 가지는 객체들을 의미한다.

자바에서는 이러한 객체들을 Bean이라고도 부른다.

 

예를 들어서.. DB와 연동되는 소프트웨어를 구현한다고 하면

프레임워크에 영향을 받지 않는.. DAO나 VO같은 클래스가 POJO 클래스가 된다고 할 수 있겠다.

또한 학사관리 시스템을 만든다면, 학교정보나 학생들의 정보가 있는 클래스가 POJO클래스라고 할 수 있을 것.

 

 

위의 그림에서 IoC의 특징을 알 수 있었다.

제어권은 프레임워크에 있기 때문에 POJO클래스를 활용하여 스프링 컨테이너에서 작업을 진행할 때, 프로그램이 흘러가는 흐름에 대한 정보같은 것을 사용자가 만들어 주면 되겠다.

 

사용자가 정의한 데이터의 흐름, 위 그림에서 보이는 Metadata는 Xml 또는 자바로 만들 수 있겠다.

 

 

 

IoC 컨테이너의 종류

1. BeanFactory

2. ApplicationContext

 

 

 

1. BeanFactory

BeanFactory는 스프링 3.0이상에서는 더이상 사용되지 않고 ApplicationContext로 대체되고 있지만, 실제 업무에서는 스프링버전이 다양할 수 있기 때문에.. BeanFactory도 알아보자..!

 

- 클래스를 통해 객체를 생성, 전달

- 상속 등 객체관의 관계를 형성, 관리

 

이정도의 기능이 있다고 한다. 말로만 봐서는 그냥 '그렇군.' 싶은데 .. 코드로 봐야겠다.

 

 

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
						http://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<bean id="test1" class="com.study.spring.beans.TestBean" />
</beans>

 

 

 

beans.xml 파일이다.

test1이라는 이름의 빈을 한개 만들었고 클래스패스를 입력해주었다.

 

 

 

public static void test1() {
	ClassPathResource resource = new ClassPathResource("com/study/spring/config/beans.xml");
	XmlBeanFactory factory = new XmlBeanFactory(resource);

	TestBean t1 = factory.getBean("test1", TestBean.class);
	System.out.printf("t1 : %s\n", t1);

	TestBean t2 = factory.getBean("test1", TestBean.class);
	System.out.printf("t1 : %s\n", t2);
}

 

 

 

BeanFactory에서 빈을 활용하기 위해서는 ClassPathResource 를 사용하여 빈을 만든 xml의 path를 정의해준다.

XmlBeanFactory 에 ClassPathResource에서 만든 변수를 넣어줌으로서 활용이 가능하다.

factory.getBean하여 정의해준 bean 객체를 가지고 옴으로써 활용할 수 있겠다.

 

t2라는 변수를 한번더 테스트 해본 이유는 IoC컨테이너의 특성을 알아보기 위해서이다.

id가 test1인 bean객체를 가져올 때 객체가 생성되어 있지 않는 상태라면 객체를 생성한 후 주소값을 받고 그 객체를 버리지 않고 가지고 있다. (IoC컨테이너에서 컨테이너는 보관의 개념인가보다.)

그러므로 똑같은 id의 bean객체를 가져오면 두 결과는 같은 객체가 되겠다.

즉, 생성된 객체는 더이상 생성되지 않으며 Singleton이라고 할 수 있겠다.

 

 

 

 

그런데

 

만약 beans.xml파일이 패키지 내부가 아닌 패키지 외부에 있다면????

 

 

 

public static void test2() {
	FileSystemResource resource = new FileSystemResource("beans.xml");
	XmlBeanFactory factory = new XmlBeanFactory(resource);

	TestBean t1 = factory.getBean("test2", TestBean.class);
	System.out.printf("t1 : %s\n", t1);

	TestBean t2 = factory.getBean("test2", TestBean.class);
	System.out.printf("t2 : %s\n", t2);
}

 

 

ClassPathResource 대신에 FileSystemResource를 사용해주면 되겠다. 그리고 xml의 경로 역시 패키지의 경로를 제외하고 beans.xml만 써주면 된다.

 

 

 

 

 

 

 

 

2. ApplicationContext

BeanFactory보다는 더 많이 활용되는 ApplicationContext이다.

 

- 클래스를 통해 객체를 생성, 전달

- 상속 등 객체관의 관계를 형성, 관리

- Bean에 이벤트를 발생시킬 수 있음

.. 등등

 

BeanFactory가 가지고 있는 기능을 포함한 더 많은 기능을 가지고 있다.

 

 

 

public static void test3() {
	ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("com/study/spring/config/beans.xml");

	TestBean t1 = ctx.getBean("test1", TestBean.class);
	System.out.printf("t1 : %s\n", t1);

	TestBean t2 = ctx.getBean("test1", TestBean.class);
	System.out.printf("t2 : %s\n", t2);

	ctx.close();
}

 

 

ApplicationContext를 사용할 때에는 ClassPathXmlApplicationContext 를 사용하여 xml의 패스를 넣어주기만 하면 해당 bean객체를 자동으로 생성해준다.

 

자동으로 객체를 생성해주는 시점은 사용자가 변경해 줄 수 있다.

Default값은 getBean을 하지 않아도 자동으로 객체를 생성해주었다.

 

BeanFactory에서의 예제와 마찬가지로 ApplicationContext도 객체를 생성하고 보관하고 있기 때문에 t1과 t2는 같은 객체라는 결과를 얻을 수 있었다.

 

 

 

 

 

beans.xml이 패키지의 외부에 있다면??

 

 

 

public static void test4() {
	FileSystemXmlApplicationContext fctx = new FileSystemXmlApplicationContext("beans.xml");

	TestBean t1 = fctx.getBean("test2", TestBean.class);
	System.out.printf("t1 : %s\n", t1);

	TestBean t2 = fctx.getBean("test2", TestBean.class);
	System.out.printf("t1 : %s\n", t2);

	fctx.close();
}

 

 

ClassPathXmlApplicationContext 대신에 FileSystemXmlApplicationContext 를 사용하여 xml파일의 path를 지정해주면 되겠다.

'JAVA > Spring' 카테고리의 다른 글

컬렉션 주입  (0) 2020.04.09
의존성 주입 (Dependency Injection)  (0) 2020.04.09
Bean 객체의 생성시점과 생명주기  (0) 2020.04.08
Maven 설정  (0) 2020.04.07
스프링 MVC 프레임워크의 구조  (0) 2020.03.31

Maven이란?

 - 자바 프로젝트의 빌드를 자동으로 해주는 도구!

 

개발자가 xml에 작성한 프로젝트 정보를 토대로 컴파일을 하고, 라이브러리를 연결하는 등의 작업을 해준다.

Maven 서버를 통해 라이브러리를 다운받아서 설정하는 작업또한 수행한다.

 

 

 

간단하게 이클립스에서 메이븐 프로젝트를 생성하고, pom.xml을 활용하여 의존성을 설정해보자.

 

spring.io 홈페이지에 접속하여 스프링 최신버전이 뭔지 보니... 

5.2.5버전이 최신버전이다. ok

 

구글에 maven이라고 검색하니까 mvnrepository 사이트가 나온다.

여기에 spring context라고 검색하면 spring버전이 나온다. 

최신버전의 사용을 해보자. 5.2.5 relese를 클릭해보았다.

 

아래 Maven탭에 있는 코드를 클릭하면 자동으로 복사된다.

해당 내용을 pom.xml파일에 붙여넣었더니 자동으로 설치가 된다.

 

 

 

<dependencies>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.5 RELESE</version>
  </dependency>
</dependencies>

 

 

 

 

로그를 활용하기 위해서

 

slf4j 와 logback도 같은 방법으로 추가했다.

 

 

 

 

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.study.spring</groupId>
	<artifactId>SpringBasic</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<!-- xml에서 사용할 속성들 -->
	<properties>
		<!-- 자바 버전 -->
		<java-version>1.8</java-version>
		<!-- 스프링 버전 -->
		<!-- <org.springframework-version>5.2.5.RELEASE</org.springframework-version> -->
		<org.springframework-version>4.3.25.RELEASE</org.springframework-version>
		<org.slf4j-version>1.7.30</org.slf4j-version>
		<logback-classic-version>1.2.3</logback-classic-version>
	</properties>

	<!-- 프로젝트에서 사용할 라이브러리 버전 -->
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${org.slf4j-version}</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>${logback-classic-version}</version>
			<exclusions>
				<exclusion>
					<groupId>org.slf4j</groupId>
					<artifactId>slf4j-api</artifactId>
				</exclusion>
			</exclusions>
			<scope>runtime</scope>
		</dependency>
	</dependencies>
    
</project>

 

 

 

xml에서 빠르게 속성을 변경하기 위해서 맨위에 버전들을 따로 정리하였다.

 

 

 

Maven Dependencies가 정상적으로 추가됨을 확인할 수 있었다.

'JAVA > Spring' 카테고리의 다른 글

컬렉션 주입  (0) 2020.04.09
의존성 주입 (Dependency Injection)  (0) 2020.04.09
Bean 객체의 생성시점과 생명주기  (0) 2020.04.08
IoC 컨테이너  (0) 2020.04.07
스프링 MVC 프레임워크의 구조  (0) 2020.03.31

+ Recent posts