@Configuration
Spring이 어떤 객체를 spring이 생성해서 관리할지 설정(bean설정)
xml문서로 설정하던 bean설정을 class기반으로 한다.
@Bean
메서드에서 리턴되는 객체를 Spring이 관리하는 bean이 되도록 한다.
xml문서로 적용해보자면
<bean id="myCar" class="com.example.demo.Car"/>
와 같다.
@Bean
public Car myCar() {//메서드의 이름이 bean의 이름(id)역할을 한다.
System.out.println("myCar()메서드 호출됨");
Car c1= new Car();
return c1;
여기서 myCar메서드의 이름은 bean의 이름(id)역할을 해준다.
package com.example.hello2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class Boot01Hello2Application {
public static void main(String[] args) {
//run()메서드가 리턴해주는ApplicationContext객체의 참조값을 변수에 담고
ApplicationContext ctx = SpringApplication.run(Boot01Hello2Application.class, args);
//해당 객체로 부터 Car type객체 얻어내기
Car car1=ctx.getBean(Car.class);
car1.drive();
}
}
싱글톤으로 관리하기 때문에 메서드를 두개로 만들어도 한번만 호출이 된다.
여러번 호출해도 Car객체는 하나만 생성된다는 의미 이다.
하나의 인터페이스로 두 개의 타입을 받아 사용할 경우 나타나는 error이다.
이럴 경우에는 메서드의 이름이 곧 bean의 이름(id)이
@SpringBootApplication어노테이션이 붙어있는main메서드가 존재하는 이 패키지를 포함해서 하위의 모든 패키지에 component scan이 자동으로 일어난다.
AOP
package com.example.aop.util;
public class WritingUtil {
//생성자
public WritingUtil() {
System.out.println("writingUtil 생성자");
}
public void wirteLetter() {
System.out.println("파란색 Pen을 준비해요!");
System.out.println("편지를 써요");
System.out.println("Pen을 닫고 마무리해요!");
}
public void writeReport() {
System.out.println("파란색 Pen을 준비해요!");
System.out.println("보고서를 써요");
System.out.println("Pen을 닫고 마무리해요!");
}
public void writeDiary() {
System.out.println("파란색 Pen을 준비해요!");
System.out.println("일기를 써요");
System.out.println("Pen을 닫고 마무리해요!");
}
}
메서드를 횡단하면서 공통적으로 수행하고 있는 것을 횡단관심사라 한다.
AOP를 적용하면 다른 곳에서 적용할 수 있다.
공통적으로 무언가 작업할 것이 수십군데 존재한다면 관리하기가 힘든데 AOP를 활용하여 효율적으로 관리할 수 있다.
횡단 메서드를 따로 관리하는 작업을 해보겠다.
AOP는 Aspect Oriented Programming 즉 관심지향프로그래밍이라는 뜻이다.
현재 수업은 maven으로 진행 중이여서
pom.xml에서 dependency를 추가해준다.
공통관심사를 작성할 aspect package를 만들어주고 그안에 WritingAspect Class를 만들어준다.
.
그리고 기존에 WritingUtil에 작성해 두었던 메서드 핵심 구문을 제외하고 모두 제거해준다.(중복된 구현을 제거해준다.)
package com.example.aop.aspect;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect //AOP사용 어노테이션
@Component
public class WritingAspect {
/*
* Spring이 관리하는 bean의 메서드가 수행되기 이전 Before에 적용되는 Aspect
* [메서드의 pattern]
* 리턴type => void
* 메서드명 => write 로 시작하는 메서드
* 메서드의 매개변수 => 없음
*/
@Before("execution(void write*())")
public void repare() {
System.out.println("파란색 Pen을 준비해요!");
}
@After("execution(void write*())")
public void end() {
System.out.println("Pen을 닫고 마무리 해요!");
}
}
@Before("execution(void write*())")
Spring이 관리하는 Bean의 메서드가 수행되는 메서드 중에
void타입
write로 시작하는 모든 메서드를 수행하기 전에 구현부를 적용해라 라는 뜻이다.
메서드의()는 메서드 모양을 뜻하는데 반드시 비어있어야 한다.=>매개변수(인자)로 아무것도 전달하지 않아야 한다.
### Aspect가 적용되는 위치를 "Point Cut"이라고 부른다. ###
Aspectj Expression
- execution(**(..))
=> 접근 가능한 모든 메서드가 point cut - execution(* test.service.*.*(..))
=>test.service 패키지의 모든 메서드가 point cut - execution(void insert*(..))
=>리턴 type은 void이고 메서드명이 insert로 시작하는 모든 메서드가 point cut - execution(*delete*(*))
=>메서드 명이 delete로 시작하고 인자로 2개 전달받는 메서드가 point cut (aop가 적용되는 위치) - execution(*delete*(*,*))
=>메서드명이 delete로 시작하고 인자로 2개 전달받는 메서드가 point cut (aop가 적용되는 위치) - excution(String update*(Integer,*))
=>메서드의 첫번째 인자는 Integer type, 두번째 인자는 아무 type이나 다되는 메서드가
point cut (aop가 적용되는 위치)
위의 메서드를 예제로 설명해 보자면
sendGreeting 즉 send로 시작하는 모든 모양의 메서드에서, 그리고 메신저 메서드가 Bean으로 등록된 메서드 중에서 수행할 메서드들을 찾아 본뒤에 AOP를 실행한다.
joinPoint.prceed( ) 는 각 메서드를 수행하기 전에 수행 할 메서드들을 조사해보고 return할지 않할지를 판단한다.
ProceddingJoinPoit는 @Around 어노테이션에서만 가능하다.
package com.example.aop.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class MessengerAspect {
@Around("execution(void send*(..))")
public void checkGreeting(ProceedingJoinPoint joinPoint) throws Throwable {
//aspect가 적용된 메서드가 호출 되기 직전에 할 작업은 여기서
//joinPoint.proceed();메서드 호출전에 aspect가 적용된 메서드가 실행된다.
joinPoint.proceed();
//aspect가 적용된 메서드가 호출 되고 나서 할 작업은 여기서 proceed()호출 이후에 한다.
System.out.println("aspect가 함께한다.😒😒😒");
}
}
Dto객체를 만들어서 joinPoint.proceed()메서드를 활용해 return해보기
package com.example.aop.util;
import org.springframework.stereotype.Component;
/*
* MemberService 메서드의 getMember()메서드에 적용할Aspect클래스를만들어서
* getMember()가 리턴해주는 MemberDto객체에 1, "김구라", "노량진"을 담아서
* 리턴이 되도록 프로그래밍 해보세요.
*
*/
@Component
public class MemberService {
public MemberDto getMember(int num) {
//객체 생성을 해서 바로 리턴해주기
MemberDto dto = new MemberDto();
return dto;
}
}
package com.example.aop.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import com.example.aop.util.MemberDto;
@Aspect
@Component
public class MemberAspect {
@Around("execution(com.example.aop.util.MemberDto get*(..))")
public MemberDto pushMemberDto(ProceedingJoinPoint joinPoint)throws Throwable{
joinPoint.proceed();
MemberDto dto = new MemberDto();
dto.setNum(1);
dto.setName("김구라");
dto.setAddr("노량진");
return dto;
}
}
🧏♂️🧏♂️🧏♂️주의!!
Aspect할 Class를 만들어 줄때에도 @Component(Bean으로등록)를 꼭해주자! 안해주니까 안돌아가지 ㅡㅡ
'수업내용' 카테고리의 다른 글
20230711 SpringBoot Controller/JSP/MyBatis (0) | 2023.07.11 |
---|---|
20230711 CSS3 Animate (0) | 2023.07.11 |
20230710 CSS3 (0) | 2023.07.10 |
20230707 CSS3 (0) | 2023.07.07 |
20230706 vue2->jQuery로 바꿔보기 (0) | 2023.07.06 |
댓글