MyBatis란?

 

SpringFramework 에서 제공하는 JDBC라이브러리를 보다 쉽게 작업할 수 있도록 만든 라이브러리이다.

Spring JDBC에서 썼던 Mapper의 역할을 확장시켜 쿼리문 작성을 모두 Mapper인터페이스에서 할 수 있도록 지원한다.

항상 반복적으로 만들어야하는 쿼리문 코드를 최대한 줄일 수 있는 라이브러리이다!

 

우선 MyBatis를 사용하기 위해서는 라이브러리를 추가해주어야 한다.

 

 

 

mvnrepository에 MyBatis라고 검색하면 이렇게 두가지가 나온다.

이 두개 모두 추가를 해주어야 한다. 

 

 

 

다음과 같이 추가해주었다. 버전관리를 위해서 프로퍼티를 지정해서 버전을 따로 빼주었다.

 

 

 

Java Configuration 파일이다. MyBatis도 DataSource를 이용하기 때문에 BasicDataSource클래스를 만들어서 커넥션 풀을 설정해준다.

 

Spring JDBC에서는 JdbcTemplate라는 것을 만들어서 그 탬플릿의 update메소드, query메소드를 이용하여 DAO클래스에서 쿼리문을 작성하여 사용하였다.

MyBatis를 이용하려면 위와 같이 SqlSessionFactory와 Mapper가 필요하다. SqlSessionFactory는 Jdbc를 처리하는 객체로서 위와 같이 dataSource를 매개변수로 받아서 setDataSource하여 셋팅을 해준다. 

중요한것은 mapper인데 개발자가 만들어 놓은 쿼리문을 관리하는 것이다.

포스팅 처음에 MyBatis는 Spring JDBC의 mapper를 확장시켜 mapper 인터페이스를 이용한다고 하였다. 위의 코드에서 MapperFactoryBean<MapperInterface>형의 빈을 만들었다. MapperInterface는 사용자가 만든 인터페이스이다. 

 

setSqlSessionFactory()하여 위에서 만든 SqlSessionFactory를 셋팅해주고 factoryBean을 반환해준다.

사용자는 빈으로 등록한 testMapper를 getBean하여 불러오고 그 빈객체를 이용하여 쿼리문을 불러올 수 있다.

 

또, mapper는 여러개 있어도 된다. 위의 예제는 한개만 만들었는데 interface이름만 다르게 해서 여러개 만들어도 상관없다.

 

 

여기까지 설정하면 이제 MapperInterface에 사용자가 원하는 쿼리문을 작성해주면 되겠다.

 

 


MapperInterface에 어노테이션을 이용하여 쿼리문을 작성해주면 된다.

@Select("select * from test") List<JdbcVO> select(); 라고 선언해주면 사용자는 select()메소드를 호출함으로서 어노테이션에 선언되어 있는 쿼리문을 실행할 수 있다.

 

위에 @Results, @Result는 왜 주석처리를 했을까???

 

생략해도 되기 때문.

 

주석처리된 구문의 의미는 '데이터베이스의 data1 칼럼에는 지정된 빈의 data1 프로퍼티에 넣겠다', '데이터베이스의 data2 칼럼에는 지정된 빈의 data2 프로퍼티에 넣겠다' 의 의미가 된다.

 

그런데, Mybatis에서는 프로퍼티의 이름과 칼럼의 이름이 같으면 알아서 그냥 주입을 해준다. POJO클래스를 만들 때, 칼럼의 이름과 프로퍼티의 이름을 맞추어 만들어 주면 @Results 을 사용하는 일을 줄일 수 있겠다.

 

 

@Insert("insert into test values(#{data1}, #{data2})") 를 보면, values가 #{data1}와 같이 되어있다.

Spring JDBC에서는 Java에서 사용했던 방식과 똑같이 ?을 넣어 쿼리문을 선언해주고, update()메소드 매개변수에 순서를 맞추어 줌으로써 ?에 값이 1:1대응으로 삽입이 되게 만들어 주었다.

MyBatist도 마찬가지로 #{data1}와 같이 선언하면, void insert(JdbcVO bean); 에서 bean변수의 프로퍼티를 알아서 찾아주어서 data1은 data1에 data2는 data2에 자동으로 주입해준다.

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

Spring Socket에 대해 알아보자! - 1. WebSocket  (0) 2020.06.18
Spring WebSocket에 대한 내용 정리  (0) 2020.06.11
Spring JDBC  (0) 2020.04.20
@AspectJ 어노테이션  (0) 2020.04.17
execution 명시자  (0) 2020.04.17
더보기

JDBC(Java Database Connectivity)는 자바에서 데이터베이스에 접속할 수 있도록 하는 자바 API이다. JDBC는 데이터베이스에서 자료를 쿼리하거나 업데이트하는 방법을 제공한다.

 

출처 : 위키백과, JDBC, https://ko.wikipedia.org/wiki/JDBC

 

Spring에서 JDBC를 이용하여 데이터베이스에 접근해볼것이다.

JDBC를 이용하기 위해서는 몇가지 라이브러리가 필요하다. 

 

 

mvnrepository에서 Spring JDBC를 검색하여 Maven코드를 추가해주었다. Spring버전과 일치하는 라이브러리를 사용하는것이 좋다. Spring버전과 일치하는 5.2.5 버전을 사용하였다.

 

 

 

Java에서 jdbc를 사용하는것과 비슷하게 Mysql connector가 필요하다. 

자바에서는 직접 커넥터를 다운로드한다음 프로젝트 빌드에 라이브러리로써 추가해주었던 기억이 난다.

Spring에서 우리는 Maven을 사용하기 때문에 아주 간편하게 의존성만 추가해주면 커넥터를 사용할 수 있다.

 

 

 

DBCP를 사용할 것이다.

 

DBCP란?

데이터베이스와 연결하는 커넥션을 미리 설정해두고 풀에 저장해두었다가 필요할때 꺼내쓰고 사용 후에는 다시 풀에 반환하는 기법을 말한다.

 

 

https://leminity.tistory.com/20#rp

 

jdbc, dbcp 차이?

오늘 일과중에 예전에 학원에서 같이 교육받았던 동생한테서 연락이 와서 이런 저런 얘기를 나누다가 요즘은 뭐 배우고 있냐고 물었더니, JDBC랑 DBCP를 배웠는데 갑자기 DBCP가 더 빠르다고 말한다. 왠지 어감이..

leminity.tistory.com

JDBC와 DBCP의 프로세서에 대해 너무 쉽게 잘 표현해주셔서 이 블로그를 참고하여 이해하였다...

커넥터를 손쉽게 관리하기 위하여 DBCP를 사용한다고 보면 되겠다.

 

 

 

pom.xml에 다음과 같이 dependency를 추가해주었다. version관리를 위해 property로 따로 버전을 빼주었다.

 

 

이제 데이터베이스와의 연동을 위한 코드를 작성할 것이다.

그 전에 미리 데이터베이스와 테이블을 만들어 놓겠다. 만들어준 테이블의 필드 속성에 맞추어서 자바코드를 작성할 예정이다.

데이터베이스는 MySQL을 사용하였고, MySQL Workbench를 이용하여 쿼리문을 작성하였다. 

사용할 필드는 data1(int형), data2(String형). 

 

 

그리고 위의 데이터 타입과 똑같은 데이터를 자바에서도 활용하기 위해서 VO클래스도 만들어주었고, 빈으로 등록했다.

 

 

 

 

 

 

 

 

 

1. 자바 설정파일

 

 

POJO클래스와 DAO클래스를 @Component를 사용하여 빈으로 등록할것이기 때문에 @ComponentScan을 이용하여 다음과 같이 해당 패키지를 스캔하도록 등록하였다.

 

먼저, BasicDataSource클래스의 source메소드를 한개 만들었다.

이 클래스는 위에서 추가해준 라이브러리의 DBCP패키지에 있는 클래스로, 커넥션풀을 관리할 수 있다. 위와같이 setter를 이용하여 Driver와 Url, Username, Password를 설정할 수 있다. 셋팅해준 속성을 리턴해준다.

 

둘째로, JdbcTemplate클래스의 db메소드를 만들었다.

이 클래스는 위에서 추가해준 라이브러리의 jdbc패키지에 있는 클래스이다. 위에서 만든 source메소드를 매개변수로 받아준다. 위와같이 BasicDataSource source로 매개변수를 받으면 빈으로 등록되어 있던 source메소드가 자동으로 매개변수로 들어가게 된다. 그 후, JdbcTemplate 클래스 변수를 만들어서 리턴해준다. 

이제 저 db변수를 사용함으로써 우리는 데이터베이스 커넥션 풀을 얻을 수 있게 되었고, 연결된 커넥션을 활용하여 데이터를 삽입, 삭제, 수정, 조회할 수 있게 된다.

 

 

 

 

 

 

 

 

 

 

2. DAO클래스 (insert, delete, update)

 

 

JdbcDAO라는 이름으로 클래스를 만든다. 우선 insert, update, delete 부터 살펴보자.

설정파일에서 커넥션풀을 함께 가진 JdbcTemplate db를 빈으로 등록해주었었다.

@Autowired하여 타입으로써 해당 빈을 가져와 사용한다.

 

insert, update 메소드는 VO(생각해보니 여기서는 데이터베이스에 접근하는 객체여서 DTO가 더 어울리는것 같다...)를 매개변수로 받아서 입력한 데이터를 데이터베이스에 insert한다.

update메소드를 사용하여 쿼리문을 삽입해준다. 이는 insert, update, delete에 공통적으로 사용한다.

쿼리문에서 ?는 사용자가 직접 넣어주어야한다. update메소드의 매개변수가 ?에 1:1대응으로 삽입된다.

insert문의 첫번째 ?는 bean.getData1(), 두번째 ?는 bean.getData2()가 들어간다.

 

자바 jdbc에서는 insert문을 넣어줄 때, PreparedStatement를 사용해서 인덱스에 대응되는 값을 한개씩 넣어주는 작업을 거쳐야 했다... 그런데 Spring Jdbc에서는 이 작업을 생략해도 알아서 1:1대응으로 삽입시켜준다.

 

delete 메소드는 int형 변수를 매개변수로 받았다. 입력하는 값이 data1의 값과 일치하면 삭제할 수 있도록 하려고 만들어 보았다.

 

 

 

main 클래스이다.

JdbcDAO 클래스를 getBean하여 가져온다. VO는 객체를 만들어서 필요한 것에 넣어주었다.

delete는 data1이 1이면 삭제할 수 있도록 1을 매개변수로 넣었다.

모두 성공적으로 동작함을 확인하였다.

 

 

 

 

 

 

 

 

 

3. select

 

select 를 따로 뺀이유는 Mapper클래스를 사용하기 때문이다.

데이터베이스 테이블의 Row가 한개라면 그냥 가져와도 상관이 없겠지만, 만약 Row가 여러개이고 그 Row의 다양한 type의 데이터가 들어가 있다면 한번에 가져오는데에 무리가 있을 것이다.

Java Jdbc를 사용하여 db를 연결할때 우리는 List형을 사용하여 Row를 담아서 사용하였다. Spring도 다를건 없다.

 

select문을 사용하여 데이터를 가지고 올때 어떤 칼럼의 값을 어느 bean에 주입할 것인지 결정해 주어야 하는데 이 역할을 하는 클래스를 Mapper클래스라고 부른다.

 

 

 

MapperClass를 다음과 같이 정의하였다. MapperClass는 SpringFramework에서 제공하는 RowMapper<T>인터페이스를 구현하여 작성한다. mapRow라는 메소드를 오버라이딩하여 작성한다. VO 객체를 만들어서 그 객체의 setter를 이용하여 데이터를 담아주었다.

Java Jdbc에서 우리는 Select문을 이용할 때, ResultSet을 이용하여 해당 Row에 데이터를 담았던것을 기억한다.

코드만 살짝 다를 뿐. 전체적 개념은 비슷하다는 것을 알 수 있었다.

매번 ResultSet을 이용하여 Row를 담는 작업을 줄여서 MapperClass에 담아 놓고 이 MapperClass를 활용해서 Select하는 것이다..

 

 

 

select부분을 추가하였다.

아까 말한것 처럼 Row가 여러개면 List의 형태로 담아서 활용한다. JdbcVO를 제네릭으로 받는 List형태의 select메소드를 만들었다. select는 다른 작업과 다르게 update()가 아닌 query()를 사용한다.

위에서 만들었던 MapperClass를 빈으로 등록하여 그 빈객체를 query메소드의 매개변수로 받는다. 이렇게 하면 MapperClass에서 했던 mapRow의 작업을 해당 select문에서 적용할 수 있는 것이다.

 

 

 

반환형이 List<JdbcVO> 이었으니까 위와 같이 하면 모든 Row의 값을 select 할 수 있을 것이다.

 

 

 

 

 

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

Spring WebSocket에 대한 내용 정리  (0) 2020.06.11
MyBatis  (0) 2020.04.21
@AspectJ 어노테이션  (0) 2020.04.17
execution 명시자  (0) 2020.04.17
AOP  (0) 2020.04.17

지금까지 Advisor를 사용할때는, Advisor로 호출할 클래스를 bean으로 등록하고 그 Advisor를 등록하여 사용하는 방법을 사용하였다.

@AspectJ를 사용하면 Advisor역할을 할 bean을 어노테이션이 붙어있는 클래스 자체에서 설정할 수 있다.

 

 

@AspectJ를 사용하기 위해서는 xml파일에 네임스페이스를 추가해주어야한다.

 

 

<aop:aspectj-autoproxy /> 를 추가해주면 advisor 클래스에 설정되어 있는 어노테이션을 분석하여 셋팅을 할 수 있게 해준다.

 

 

 

BeanTest1이라는 클래스를 만들고 @Component 를 써주어 빈으로 등록해주었다. 

AdvisorClass 라는 클래스를 만들고 @Component 를 써주어 빈으로 등록해주었다. Advisor역할을 할 빈을 여기에 설정할 예정이다. 컴포넌트 어노테이션을 써주었기 때문에 컴포넌트 스캔을 해주어야 한다.

 

 

이렇게 지정해주고 Advisor클래스에 @AspectJ 어노테이션을 이용해서 설정을 해주겠다.

 

 

 

이런식으로 @AspectJ 를 붙여주고 그 클래스안의 메소드(advice)에 어노테이션을 붙여서 선언해준다.

각각 @Before, @After, @Around, @AfterReturning, @AfterThrowing 이며 속성에는 execution명시자를 넣어서 관심사를 설정해주었다. xml파일에서 설정해준것과 형식은 유사했다.

 

 

 

xml 에서 말고 당연히 java configuration에서도 할 수 있을것이다.

 

 

<aop:aspectj-autoproxy /> xml에서 이렇게 했다면 java에서는 @EnableAspectJAutoProxy 해주면 된다.

 

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

MyBatis  (0) 2020.04.21
Spring JDBC  (0) 2020.04.20
execution 명시자  (0) 2020.04.17
AOP  (0) 2020.04.17
@Component 어노테이션  (0) 2020.04.15

 

execution 명시자는 포인트컷을 명시할 때 어드바이스들이 동작할 수 있도록 해주는 표현식 문법이다.

 

 

출처 : [토비의 스프링 3.1] 6장_AOP_포인트컷 표현식 문법

 

execution 명시자는 위의 그림과 같이 접근제한자, 리턴타입, 클래스이름, 메소드이름, 매개변수 의 순으로 이루어져있다.

접근제한자는 public만 지원하기 때문에 생략한다. 클래스이름은 패키지까지 적어주어야하는데 이 역시도 *(Asterisk) 이면 생략이 가능하다.

패턴에 *이나 ..을 사용하여 줄일 수 있는데 *과 ..의 의미는 다음과 같다.

 

 

*(Asterisk) : 하나의 모든 것을 의미한다.

.. : 개수 상관 없이 모든 것을 의미한다.

 

 

 

어떻게 쓰이는지 xml Configuration 파일을 살펴보자. 

 

 

 

여러가지 상황에 대해서 설정을 해보았다. 

 

expression="execution(void com.study.spring.beans.TestBean2.method1())"

-> 매개변수에 아무것도 설정되어 있지 않기 때문에 매개변수가 없는 void형의 method1 메소드에만 포인트컷이 적용된다.

 

 

expression="execution(void com.study.spring.beans.TestBean2.method1(int))"

-> 매개변수에 int 한개가 들어가 있다. 같은 이름의 메소드 method1이 매개변수만 다르게 여러개가 있으면 그 중에서 매개변수를 int로 받는 advice만 적용된다.

 

 

expression="execution(void com.study.spring.beans.TestBean2.method1(int, int))"

-> 매개변수에 int 두개가 들어가 있다. 매개변수의 개수까지 철저하게 지키기 때문에 위에처럼 int 한개만 받는 advice는 적용이 안되고 두개가 들어가 있어야 적용된다.

 

 

expression="execution(void com.study.spring.beans.TestBean2.method1(*))"

-> *는 모든 타입을 받지만 갯수는 한개! 예를들어 매개변수가 java.lang.String (String은 자바에서 클래스이기 때문에 이렇게 입력해주어야 한다.) 이면 적용이되지만 int, double 이렇게 두개면 적용이 안된다.

 

 

expression="execution(void com.study.spring.beans.TestBean2.method1(..))"

-> ..는 타입, 갯수 상관없이 모든 매개변수를 받는다. method1이라는 메소드에 매개변수의 타입이 여러 형태이고 갯수가 여러개여도 상관이 없다.

 

 

expression="execution(void com.study.spring.beans.TestBean2.*(..))"

-> 메소드부분이 *처리가 되어 있다. com.study.spring.beans.TestBean2 라는 클래스에 있는 모든 메소드에 어떤 매개변수가 들어가도 다 적용할 수 있다는 뜻이 되겠다.

 

 

expression="execution(void *.*(..))"

-> 클래스부분까지 *처리가 되어 있다. 반환형이 void인 모든 패키지의 모든 클래스의 모든 메소드에 어떤 매개변수가 들어가도 다 적용을 할 수 있다는 뜻이다.

 

 

expression="execution(* *.*(..))"  /  expression="execution(* *(..))" 
-> 반환타입까지 *처리가 되어 있다. 모든 반환타입, 모든 패키지, 모든 클래스, 모든 메소드, 모든 매개변수에 다 적용된다. 클래스는 *이면 생략할 수 있기 때문에 후자의 형태로 적어도 상관이 없다.

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

Spring JDBC  (0) 2020.04.20
@AspectJ 어노테이션  (0) 2020.04.17
AOP  (0) 2020.04.17
@Component 어노테이션  (0) 2020.04.15
JSR-250 어노테이션  (0) 2020.04.11

AOP이란?  Aspect Oriented Programming : 관점 지향 프로그래밍 

 

하나의 프로그램을 관점(관심사)라는 논리적인 단위로 분리하여 관리하는 개념이다. 여기에서 관심사란 메소드 호출이나 특정주소를 요청하는 등의 행위들을 말한다. 로깅, 감사, 선언적 트렌젝션, 보안, 캐싱 등 다양한 곳에서 사용이 된다. 

AOP는 원래 실행되는 코드는 건드리지 않고 AOP를 사용함으로써 모듈을 삽입,호출하는 것에 의의가 있다.

 

 

 

AOP 동작과정

 

왼쪽의 메소드 호출이라고 되어있는 부분이 바로 관심사 부분이 되겠다. 메소드 호출하는 행위자체를 관심사로 등록했다면 호출된 메소드의 전, 후로 모듈을 삽입하여 사용하는 것이 기본적인 AOP의 개념이자 동작과정이다.

 

조금 더 쉽게 생각해보면 특정 메소드를 호출하게 되면 그 호출을 가로채서 다른 메소드를 먼저 호출하거나, 아니면 호출된 메소드 이후에 호출하거나 .. 섞어서 사용할 수 있겠다.

 

웹 프로젝트에서는 특정 웹 페이지를 요청하였을 때, 로그인 여부를 검사하게 하는 것처럼 요청이 발생할 때마다 공통적으로 처리해야할 것이 있을 경우에 사용할 수 있을 것이다!

 

 

 

AOP에서 사용되는 여러가지 용어에 대해서 알아보자. 위의 AOP 동작과정 그림기반으로 용어를 생각하면 이해가 빠르다.

 

- Join Point : 모듈이 삽입되어 동작하는 실제 위치이다. 관심사가 메소드 호출이라면 위의 그림에서 왼쪽 메소드 호출 부분이 Join Point가 될 것이다.

 

- Point Cut : 다양한 Join Point중에서 어떤 것을 사용할 것인지 선택하는 것이다. Advice를 적용할 조인 포인트를 선별하는 작업 또는 그 기능을 위한 모듈을 말한다. 즉, 메소드를 선정하는 기능을 가진것을 의미한다.

 

- Advice : 타겟에게 제공할 부가기능을 담은 모듈을 말한다. 다시말해, Join Point가 벌어질 때 동작할 코드라고 할 수 있겠다.

 

- Advisor : Point Cut과 Advice를 가지고 있는 오브젝트이다. 어떤 부가기능(Advice)를 어디에(Point Cut) 전달할 것인가를 알고 있는 모듈이라고 할 수 있다.

 

- Weaving : Advice를 핵심 로직 코드에 적용하는것을 말한다. 메소드를 호출하는 사건이 벌어졌을 때 메소드 전,후에 코드를 삽입해서 하나의 동작으로 만드는 행위를 말한다.

 

- Aspect : 한개 또는 그 이상의 Point Cut과 Advice조합으로 만들어진 오브젝트이다. Advisor는 아주 단순한 Aspect라고 볼 수 있다.

 

 

 

 

실제로 동작하는 메소드(메소드의 호출이 관심사이며 Point Cut으로 인해 Advice가 동작한다는 가정)인 Advice의 종류에 대해서 알아보자.

 

- before : 타겟 메소드 호출 전에 동작하는 Advice이다.

 

- after : 예외발생 여부와 관계 없이 타겟 메소드의 동작이 완료되면 동작하는 Advice이다.

 

- around : 타겟 메소드 호출 전, 후에 동작하는 Advice이다. 

 

- after-returning : 예외 없이 호출된 메소드의 동작이 완료되면 동작하는 Advice이다. 예외가 없어야 동작한다.

 

- after-throwing : 타겟 메소드 동작 중 예외가 발생하면 동작하는 Advice이다.

 

 

 

지금가지 알아본 AOP의 용어들을 실제로 코드에서 어떻게 사용되는지 알아보자.

우선, AOP사용을 위한 의존성을 추가해주어야 하며 aop네임스페이스도 선언해주어야 한다.

 

 

 

mvnrepository에서 AspectJ Weaver를 검색한 후 maven코드를 복사해준다.

 

 

Version관리를 위해 버전을 xml property에 설정해주고 변수로 Version을 설정해주었다. 

 

 

xml configuration 파일에 위와 같은 네임스페이스를 추가해주었다. xmlns:aop와 xsi:schemaLocation에 aop부분을 추가한다.

 

 

AdvisorClass라는 클래스를 위와 같이 정의해준다. Advisor종류에서 살펴보았던 before, after, around를 사용해보겠다. 각각 beforeMethod, afterMethod, aroundMethod라는 이름으로 Advisor를 정의해주었다. 

 

around는 다른 2개와 조금 다르게 생겼다?

around는 ProceedingJoinPoint라는 클래스를 매개변수로 받는다. 예외발생을 하여 thorws Throwable도 해준다.

before과 after는 실행위치가 명확하다. 타겟 메소드의 전과 후.

그런데 around는 전과 후의 경계가 약간 애매하다.. 그래서 타겟 메소드(원래 호출할 메소드)의 위치를 직접 정해준다.

 

위에서 한것 처럼 pjp.proceed() 하면 원래 메소드가 호출된다. 

타겟 메소드가 반환값이 없으면 상관이 없는데 반환값이 있을수도 있겠다. Object 형 변수로 받아서 반환을 해주자.

 

 

 

xml Configuration 파일이다. 방금 설정한 Advice를 담고있는 AdvisorClass를 advisor1이라는 이름의 빈으로 등록해준다.

aop:aspect를 advisor1을 참조하게 설정함으로써 advisor1 애스펙트가 만들어졌고, point1이라는 이름으로 Point Cut한개를 만들어 주었다.

expression은 관심사를 설정한다. 위와같이 execution(* method1())로 설정하면 패키지,클래스와 상관없이 method1이라는 메소드가 실행되는 행위를 관심사로 설정하며 이를 실행하는 것을 포인트 컷으로 설정한다는 의미이다. execution명시자에 대해서는 다음 포스트에서 더 자세하게 설명하겠다.

 

AdvisorClass에서 정의한 메소드를 aop:before, aop:after, aop:around 를 사용해서 가져온다. point1이라고 설정해주었던 Point Cut을 pointcut-ref를 해서 참고(사용)한다.

 

 

 

타겟메소드는 method1()이다. bean1.method1()을 해줄 때 TestBean1이라는 이름의 빈안에 있는 method1() 메소드를 불러왔다. 

 

 

'metho1 메소드'라는 문자열을 찍어주는 method1() 메소드 앞뒤로 before, after가 실행됨을 확인할 수 있으며 method1()메소드를 감싸는 around메소드가 출력된것을 확인하였다. 함께 찍어봄으로써 before, after보다 around가 더 타겟메소드와 가깝게 실행된다는것을 알 수 있었다.

 

 

 

 

 

 

이번에는 afterReturning과 afterThorwing 을 알아보자. 

AdvisorClass에 위와 같이 메소드 두개를 추가해주었다. afterThrowingMethod는 예외가 발생할 때 동작하는 Advice이기 때문에 매개변수로 Throwable을 받고 예외문을 출력까지 해보겠다.

 

 

 

 

 

point2라는 이름의 Point Cut을 한개 더 선언했다. 이번에는 위의 예제와 구분하기 위해서 method2를 만들었고, expression="execution(* method2())"를 선언해줌으로써 관심사를 '패키지와 상관없이 method2()를 호출하는 행위' 로 설정하였다. 

aop:after-returning, aop:after-throwing을 선언했다. aop:after-throwing는 예외로 던져주었던 변수 e를 throwing="e"로 선언해주어야 한다. 

 

 

 

method2()의 반환값이 int형이기 때문에 다음과 같이 출력해주었다. method2()의 반환값이 오류가 없다면(result=100)

 

 

 

afterReturningMethod메소드가 출력되고,

오류가 있다면(result =10/0) 

 

 

예외문과 함께 afterThrowingMethod 메소드가 출력된다

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

@AspectJ 어노테이션  (0) 2020.04.17
execution 명시자  (0) 2020.04.17
@Component 어노테이션  (0) 2020.04.15
JSR-250 어노테이션  (0) 2020.04.11
Annotation을 이용한 빈 설정  (0) 2020.04.11

@Component 어노테이션을 이용하면 Bean Configuration 파일에 Bean을 따로 등록하지 않아도 사용할 수 있다.

빈 등록자체를 빈 클래스 자체에다가 할 수 있다는 의미이다.

 

@Component 어노테이션은 기본적으로 타입기반의 자동주입 어노테이션이다. 

@Autowired, @Resource와 비슷한 기능을 수행한다고 할 수 있겠다.

 

@Component 어노테이션을 xml 설정파일에서 설정하는 방법이다.

 

 

 

 

 

 

 

1. Xml 설정파일에서 @Component 어노테이션 설정하기

 

xml파일에 <context:component-scan base-package="패키지경로" /> 태그를 설정해주면, 지정된 패키지 안에 있는 bean클래스의 어노테이션을 분석할 수 있도록 지정해주는 것이다.

 

설정한 패키지 경로 안에 bean클래스를 만들고 @Component 어노테이션을 붙여주면 해당 bean클래스는 자동으로 빈이 생성될 수 있게 된다.

 

아이디를 사용하지 않고 타입으로 빈을 지정해서 찾는거랑 비슷한 느낌이다... 이름이 없기 때문에 타입으로서 빈을 받아낼 수 있다.

 

 

 

이렇게 패키지를 등록해주고 패키지 아래에 comBean1 이라는 클래스를 만들어서 @Component 어노테이션을 붙여주었다.

 

 

 

그 후 실행해보면, 별다른 빈을 등록하지 않아도 comBean1클래스가 빈에 등록되어 있다는것을 확인할 수 있다.

 

 

 

 

 

 

 

 

 

2. java configuration 파일에서 @Component 설정하기

 

xml에서 설정한 것을 당연히 자바 configuration 파일에서도 할 수 있다.

 

@Configuration 어노테이션 아래에 @ComponentScan(basePackages="패키지 경로") 이라는 어노테이션을 써줌으로써 해당 패키지안에 있는 bean클래스의 어노테이션을 분석할 수 있도록 설정해줄 수 있다.

 

javacb1이라는 빈을 만들어서 패키지안에 등록되어 있는 bean클래스(comBean 클래스) 를 return하는 빈을 등록해준다.

이 빈을 메인에 출력해보면, 

 

 

 

 

다음과 같이 그냥 comBean1.class를 가져오는것 만으로도 빈을 가져올 수 있다.

@Component 어노테이션은 타입기반으로 빈을 등록해주는 놈이라서 이름을 써주지 않고 클래스만 넣어주면 된다.

 

 

 

 

 

 

 

 

3. @Component

 

위에서 설명했던것 처럼 @Component는 타입을 통해 등록된 Bean객체를 가져올 수 있다.

또한 IoC컨테이너 객체를 생성할 때 자동으로 객체가 생성되며, Singleton이다.

 

 

 

 

 

 

기본생성자를 만들고 실행해서 생성자가 언제 호출되는지를 확인해보았다.

getBean하여 객체를 가져오기 전에 comBean1클래스의 기본생성자가 호출된 모습을 볼 수 었다.

또한, 빈 객체의 범위는 싱글톤이기 때문에 객체를 두번 호출하면 같은 객체가 출력되는것을 확인하였다. 

 

 

 

 

 

 

 

4. @Component("빈 이름")

 

@Component 어노테이션도 빈을 설정하는 어노테이션이기 때문에 빈의 이름을 따로 정해줄수도 있다. 괄호열고 빈이름을 적어주면 된다. 그런데 @Component는 특징이 있다.

 

한개의 패키지 내에서 여러개의 이름으로 빈을 등록하는 것이 불가능하다는 것이다.

 

@Component는 이름을 셋팅할 때 쓴다기보다는 이름이 없이 딱 타입을 통해서 가지고 오는 빈들... 즉, 전체 프로그램에서 특정 클래스타입의 빈을 딱 한번 등록해서 사용할 경우에 사용된다.

 

같은 클래스 타입으로 여러개의 이름으로 빈을 등록하려면 xml파일을 이용하거나 java configuration 파일을 이용해서 빈을 여러개 정의해주면 되겠다.

 

 

 

이로 인해서 @Bean 과 @Component 를 사용해야 할 경우를 다음과 같이 비교해볼 수 있다.

 

- @Bean :             개발자가 Class코드를 수정할 수 없을 때

                           같은 클래스 타임의 Bean을 여러개 등록할 때

 

- @Component   개발자가 Class코드를 수정할 수 있을 때

 

 

 

 

다음과 같이 이름을 "test"라고 지정하고 @Component를 사용하였다. 

 

 

 

 

이렇게하면, test라는 이름으로 빈을 가져오는것이 가능하다.

위에서 말했듯이 @Component를 사용하면 빈의 이름을 같은 패키지 안에서 여러개 지정할 수 없다..

@Component("test1", "test2")와 같은 형태는 존재하지 않는다는 것이다.

 

따라서, 같은 타입의 빈 클래스를 여러개이름을 부여하여 사용하기 위해서는 java configuration 파일을 사용한다. 

 

 

 

 

 

 

 

5. @Component 의 여러 가지 설정

 

 

@Component

@Lazy

-> getBean을 할 때 객체를 생성하는 Lazy속성이다. 

 

 

@Component

@Scope("prototype")

-> Default가 싱글톤으로 설정된 객체 생성에 범위를 prototype으로 바꾸어준다. 이렇게 하면 객체가 생성될때마다 새로운 객체가 생성된다.

 

 

 

@PostConstruct, @PreDestroy

-> @Component로 설정된 bean클래스에 @PostConstruct, @PreDestroy 어노테이션이 설정되어 있는 메소드는 각각 객체가 생성되기 전에 호출되는 메소드, 객체가 소멸된 후에 호출되는 메소드로 지정된다.

@Bean을 사용할때는 initMethod="initmethod" 와 같이 빈을 만들때마다 생성을 해주어야 했지만 @Component에@PostConstructor, @PreDestroy을 설정하면 객체가 생성되기 전 후로 메소드를 계속 호출 가능하다.

 

 

 

 

 

 

 

 

6. @Component 의 자동주입 

 

@Component어노테이션을 사용하여 자동주입하는것은 @Bean 어노테이션을 이용하는 것과 동일하다..

예제를 보며 한개한개 살펴보자.

 

 

@Autowired

-> 타입을 통한 자동주입이다. 변수에 설정해주면 자동으로 타입에 맞는 빈을 찾아서 setter를 통한 주입을 해준다.

 

 

@Qualifier("빈 이름")

-> 이름을 통한 자동주입이다. @Autowired 와 함께 써준다. 

@Component("obj1") 어노테이션을 이용하여 obj1이라는 이름의 빈을 생성하였다고 한다면, @Qualifier("obj1") 을 사용해서 이름을 통한 자동주입을 해준다.

 

 

@Resource(name="빈 이름")

-> JSR-250 에서 제공하는 어노테이션으로 @Autowired @Qualifier("빈 이름") 과 같은 역할을 한다. 동작은 위와 동일하게 하겠다.

 

 

생성자를 통한 주입

-> @Component 어노테이션을 사용하여 빈을 등록한 comBean1과 comBean2가 있다고 하자.

TestBean1이라는 클래스의 생성자에서 저 두 타입의 빈을 주입한다고 하면, 

 

이런식으로 해주면 되겠다. 별다른 설정없이 타입을 기반으로 빈을 찾아서 생성자를 통해 주입을 해준다. 

예전에 @Required라는 어노테이션을 설명한적이 있다. 이는 반드시 값을 주입해야하는 프로퍼티를 설정하는 어노테이션으로써, @Required를 setter에 붙이면 반드시 setter를 통해 값을 주입해야하는 역할을 하는 어노테이션이었다.

 

그런데 spring5.1 부터는 @Required를 사용하지 않는다. 

반드시 주입해야할 프로퍼티가 있다면 위의 예제와 같이 @Component로 빈을 등록하고(사실 @Autowired를 사용해도 상관은 없다.) 생성자를 통해서 값을 주입하는것을 더 권장한다.

 

 

 

int, String과 같은 기본형은 자동주입을 해줄수 없으므로 @Value 어노테이션을 이용하여 값을 지정할 수 있다.

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

execution 명시자  (0) 2020.04.17
AOP  (0) 2020.04.17
JSR-250 어노테이션  (0) 2020.04.11
Annotation을 이용한 빈 설정  (0) 2020.04.11
Java를 이용한 Bean 객체 주입  (0) 2020.04.10

JSR-250은 자바플렛폼 공통 어노테이션이다. 기본 자바에서는 제공하지 않기 때문에 적용을 위해서는 라이브러리를 반드시 추가해야 한다. 

JSR-250 어노테이션 종류는 @Resource, @PostConstruct, @PreDestroy가 있다.

 

 

JSR-330 에서는 @Autowired 및 @Qualifier 어노테이션과 비슷한 @Inject  @Named 어노테이션이 있는데 이는 추후에 포스팅하도록 하겠다.

오늘은 JSR-250 어노테이션에 대해서 알아보자.

 

 

 

 

 

먼저, 의존성을 추가해보자

 

 

mvnrepository에서 jsr 250이라고 검색하면 다음과 같은 화면이 나온다.

Maven부분을 복사해서 pom.xml에 의존성을 추가하였다. 

 

 

version이 바뀔 수도 있기 때문에 javax.annotation-version이라는 이름의 변수로 따로 빼주었다.

 

 

 

 

 

 

 

 

1. @Resource

 

 

이렇게 @Autowired와 @Qualifier 어노테이션을 이용해서 타입기반의 bean을 자동주입할 때, id에 따라서 각각 주입할 수 있도록 설정해주었다. 

@Resource 어노테이션은 이걸 하나로 합쳐서(?) 사용할 수 있는 어노테이션이다.

 

 

 

빈 설정파일에 다음과 같이 data1, data2 라는 이름의 빈이 등록되어 있다고 하면, 

 

 

 

이렇게 @Resource(name="빈 이름") 어노테이션을 이용하여 타입기반으로 자동주입을 하지만 id로 빈을 찾아주어 주입할 수 있다. 

 

 

 

 

 

 

 

 

 

2. @PostConstruct 과 @PreDestory

 

 

 

TestBean 파일에 다음과 같이 init() 메소드와 destroy() 메소드를 정의해주고 

 

 

 

 

설정파일에서 Bean을 등록할때 다음과 같이 @Bean(initMethod="init", destroyMethod="destroy") 어노테이션을 이용하여 빈을 등록하면 객체가 생성되기 전에 init메소드가 호출되고, 객체가 소멸될 때 destroy메소드가 호출되도록 설정할 수 있었다.

 

 

@PostConstruct 과 @PreDestory 어노테이션을 이용하면 @Bean을 사용하여 빈을 등록할때 번거롭게 메소드들을 등록해주지 않아도 된다.

 

 

 

 

TestBean파일에서 init메소드와 destroy메소드를 정의할때 @PostConstruct 과 @PreDestory 어노테이션을 붙여서 정의해주면 자동으로 객체가 생성되기 전과 소멸될 때 메소드가 호출되도록 설정할 수 있다.

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

AOP  (0) 2020.04.17
@Component 어노테이션  (0) 2020.04.15
Annotation을 이용한 빈 설정  (0) 2020.04.11
Java를 이용한 Bean 객체 주입  (0) 2020.04.10
Java코드를 활용한 Bean 등록  (0) 2020.04.10

어노테이션(Annotation) 이란???

 

 

앞에서도 @Bean과 같은 어노테이션을 사용하여 포스팅 하기는 했지만 정확히 어노테이션이 어떤것인지에 대한 설명이 없었던것 같다..

 

Annotation 의 사전적 의미는 '주석'이다. 

자바에서는 // 또는 /**/ 과 같이 코드에서 실제 동작하지 않는 즉, 의미가 없는 부분을 주석이라고 한다.

어노테이션도 마찬가지이다. @를 사용한 주석이다. 어노테이션 자체로 어떠한 동작을 하는것은 아니지만 어노테이션을 써줌으로써 자바코드에 '주석'을 달아 특별한 의미를 부여한 것을 의미한다.

 

' 프로그램 코드의 일부가 아닌 프로그램에 관한 데이터를 제공, 코드에 정보를 추가하는 정형화된 방법.

출처: https://sjh836.tistory.com/8 [빨간색코딩]

 

 

자바코드에서 이러한 어노테이션을 이용하여 빈을 설정하는 방법에 대해서 알아보도록 하자.

 

 

 

 

 

 

 

1. @Required

 

Required 어노테이션은 반드시 주입해야 할 프로퍼티를 설정하는 어노테이션이다.

POJO클래스의 setter메소드에 @Required를 설정해주면 필드 데이터는 null이면 안되고, 무조건 setter를 이용하여 값을 주입해주어야 한다. (xml 파일에서 bean을 등록할 때 해당되는 내용)

 

그러나 ...

 

Spring 5.1 이후부터는 더이상 @Required를 쓰지 않는다..

반드시 입력해야 하는 값은 @Required 어노테이션을 사용하지 않고 생성자를 이용한 주입으로 해주어야 한다...

예를들어, 매개변수가 없는 생성자를 만들지 말고 매개변수로 data를 받는 생성자를 만들면 객체를 만들때 무조건 데이터를 넣어주어야 하기 때문에 이와 같이 사용한다.

 

 

 

어노테이션을 사용하기위해서는 다음과 같이 xml을 조금 수정해야한다.

xmls:context 속성을 추가해야하고, xsi:schemaLocation속성에 context를 추가해야 하며 

<context:annotation-config/> 태그를 추가해 주어야 한다.

외우기보다는 추가해야한다고 알아두면 되겠다..

 

 

req라는 이름의 bean을 추가해준다. 

 

 

 

TestBean9클래스의 setter에 다음과 같이 @Required어노테이션을 추가해 준 후 컴파일,실행 해보면

 

 

오류....  값을 무조껀 넣어주어야 하기 때문이다.

 

 

 

다음과 같이 property 속성을 이용하여  data1에 값을 넣어준 후 실행해보면

 

 

 

오류가 나지 않고 실행이 되는 것을 볼 수 있었다.

 

 

 

 

 

 

 

 

2. @Autowired

 

@Autowired는 타입기반 자동주입 설정이다. 

예를들어, POJO클래스의 setter메소드에 @Autowired 설정을 해주면 setter에 들어갈 매개변수의 타입과 같은 빈을 찾아서 자동으로 주입해준다. 

이 때, 설정파일(xml 또는 java파일)에는 자동주입이 될 빈이 (..당연하게도) 정의가 되어있어야 한다.

 

@Autowired는 변수에도 설정이 가능하다.

자동주입을 변수에 설정하는것으로 자동으로 setter메소드가 추가되어 setter메소드를 통해 주입을 하게 된다. 데이터를 꺼내올 getter만 정의하여 사용하면 되겠다. 

 

 

xml과 비슷하기 때문에 자바파일에서 빈 등록하는 예제만 해보겠다.

setter에 설정하는거말고 변수에 설정하는 예제로 해보자.

 

 

 

 

TestBean9을 재활용했다. DataBean2 타입의 data2를 추가하였는데, @Autowired로 설정해주고 getter 메소드만 만들어주었다. setter메소드는 어노테이션을 써줌으로서 자동으로 생성되기 때문이다. 

 

 

 

bean 설정파일에는 다음과 같이 빈을 등록해 주었다.

@Autowired는 타입 기반으로 자동주입을 해주기 때문에 bean의 이름은 상관이 없다. anything으로 설정했다.

그리고 auto라는 이름으로 TestBean9 형태인 빈을 만들었다.

 

 

 

그리고 다음과 같이 getBean한 후, 그 빈의 getData2해서 DataBean2형태의 빈이 자동으로 잘 주입되었는가 출력을 해보았다.

 

 

 

 

성-------------공

 

 

 

 

 

 

 

 

3. @Qualifier

 

@Qualifier 어노테이션은 @Autowired의 짝꿍이다. @Autowired 어노테이션은 타입기반으로 자동주입을 해주는 어노테이션임을 위의 예제에서 알아보았다. 만약 자동주입을 해야하는 빈중에서 같은 타입의 빈이 여러개 있으면 @Autowired를 써주어도 에러가 날 것이다.

 

이때 써주는 어노테이션이 @Qualifier이다. 타입이 같은 빈이 여러개 있으면 id로써 자동주입하는 빈을 찾아주는 어노테이션이다. 

@Qualifier("빈의 이름") 형태로 써준다.ㄴ

 

 

 

TestBean9 클래스에 DataBean2형태의 변수를 한개 더 선언해준다.

 

 

2번의 예제와 똑같이 구성되어 있는 예제파일에서 빈 설정파일이 위와 같이 되어 있다고 가정하자.

@Autowired 어노테이션은 타입기반 자동주입이기 때문에 이름이 상관없다고 했었다. 그런데 저렇게 같은 타입의 빈이 2개 이상이 되면 어떤 빈을 넣어야할지 모르기 때문에 에러가 발생한다.

 

 

 

@Qualifier 어노테이션을 이용해서 빈의 id를 설정해주었다.

 

 

 

 

성---------------------공

 

 

 

 

 

 

4. 생성자를 통한 주입

 

xml에서 bean을 설정할때 사용하는 방법에 대애서 먼저 알아보도록 하겠다.

1번 예제에서 처럼 xml파일에 어노테이션을 이용한 빈을 등록하기 위해서는 <context:annotation-config/> 을 포함하여 xml파일의 속성을 조금 바꾸어 주어야 한다고 설명하였다.

xml파일에서 생성자를 통하여 빈을 자동주입하면 참조변수 타입은 자동으로 주입되고, 기본 자료형 및 문자열은 사용자가 설정해주어야 한다.

 

 

 

 

TestBean10을 다음과 같이 구성하였다. 생성자에는 매개변수로 DataBean와 DataBean2 형태인 변수를 받는다.

 

 

 

 

xml 파일에 다음과 같이 bean을 등록해준다.

id값이 없는 DataBean형의 bean과 DataBean2형의 bean이 등록이 되어있고, 

TestBean10형의 bean이 autoCon이라는 id를 가지고 등록되어 있다. autoCon에는 따로 아무 설정도 해놓지 않았다.

 

이렇게 xml파일을 구성하면 <context:annotation-config/> 설정덕분에 생성자의 타입을 보고 일치하는 타입을 자동으로 주입해준다. 

 

 

 

 

 

data1과 data2는 주입해준게 없으니까 아무값도 들어가지 않고, data3과 data4는 객체가 자동으로 주입되어 실행되는 모습을 볼 수 있었다.

 

data1과 data2를 객체가 생성될 때 설정해주려면 @Value태그를 쓰면 된다.

 

 

 

 

 

다음과 같이 생성자에 @Value 어노테이션을 넣어 직접 주입해준 후 실행해보면 

 

 

 

이와 같은 결과를 얻을 수 있다.

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

@Component 어노테이션  (0) 2020.04.15
JSR-250 어노테이션  (0) 2020.04.11
Java를 이용한 Bean 객체 주입  (0) 2020.04.10
Java코드를 활용한 Bean 등록  (0) 2020.04.10
자동 주입  (0) 2020.04.10

+ Recent posts