스프링 AOP(Aspect Oriented Programming) - 관점지향프로그램
OOP(Object Oriented Programming) - 객체지향프로그램
객체지향의 좋은점은? 중복성을 배제하려 하는 것 모든 명령어들이 함수단위로 쪼개진다. 똑같은 일을 반복적으로 처리하지 말자가 되는 것이다. 메인 안에다 코드를 짜는데 중복이 되고 그러면 정말 싫어한다. 이렇게 되면 중복되는 코드를 함수로 빼버리는 것이다. 그리고 중복되는 코드를 쓰고싶으면 그 함수를 갔다가 다시 오게 하는 것이다.
함수를 갔다가 돌아올 때는 메모리를 소멸시키기 떄문에 좋고 중복성도 배제되니 좋아진다.
그리고 결합도도 낮춰야하는데 낮춰진다. ---> 우리가 배운건 상속 다형성이 들어가면서 결합도를 낮추게 되는 것이다.
코드를 우리가 뺐는데도 중복이 되는게 문제다. ---- 100% 마이바티스 쪽이다.
이렇게 쪼개놨는데도 중복되는 부분이 생긴다.
AOP에서 이런 중복마저도 중복시키지 않겠다.
OOP를 보완하겠다는 것이지 OOP를 배제시키는게 아니다.
스프링은 왜 쓰느냐? 스프링은 자바기반이기 때문에 쓰고있다.
스프링에서 사용하는 AOP를 사용한다. AOP는 함수 단위로 적용된다.
진범( ) {
입실
수업
퇴실
}
훈( ) {
입실
카톡
퇴실
}
길동( ) {
공부
}
함수 중에서도 내가 똑같은 코드가 중복되는 함수도 있지만 중복되지 않은 함수도 있다.
이런식으로 여러 종류의 함수가 있을 때 중복되는 코드를 넣지말아라 하는 것이다.
우리는 코드 안에서 나눠주는 것이다.
중복되는 코드를 공통의 코드라고 한다.
함수의 가장 중요한 것을 핵심 코드라고 한다. --- 꼭 해줘야 하는 코드 (중복되지 않은 코드)
중복되는 코드를 직접적으로 넣지말아라 하는 것
중복되는 입실 퇴실 -- 이런 코드를 빼버린다.
공통코드가 들어가는 함수를 따로 잡는다.
공통 ( ) {
입실
퇴실
}
공통코드를 따로 관리해서 들어간다.
그리고 우리가 필요하게 되면 입실과 퇴실을 그 자리에 삽입하는 것이다.
특징은 따로 공통된 코드를 가지고 있다가 필요한 부분이 있으면 삽입하는 것이 AOP이다.
다이소에 갔을 때 컵이 나란히 배열되어있다.
A의 컵을 사면 볼펜을 같이 주겠다. 볼펜이 삽입돼서 들어온다는 것이다.
진범이와 훈이 함수를 호출하면 공통의 코드를 삽입하겠다는 것
이렇게 삽입되는 코드를 가지고 있는 함수를 타겟이라고 얘기한다.
함수에서는 진범, 훈, 길동이 있는데 이런 대상자들을 조인포인트라고 한다.
길동같은 삽입대상자에서 빠지고 / 진범, 훈만 삽입대상자인 것을 포인트컷이라고 한다.
Aspect란
어플리케이션의 핵심 기능은 아니지만, 어플리케이션을 구성하는 중요한 요소이고, 부가적인 기능을 담당하는 요소
(공통의 코드로 들어가는 것) -- 중요하지 않다는 것은 아니지만 부가적인 기능으로 들어가는 것
Aspect = Advice(언제 집어넣을 것인지)
ex) after-- 앞에만 집어넣는다.
before -- 뒤에만 집어넣는다.
arround -- 앞뒤로 집어넣는다.
+ Pointcut
: 어드바이저는 아주 단순한 형태의 애스펙트라고 볼 수 있다
AOP란
어플리케이션의 핵심적인 기능에서 부가적인 기능을 분리해서 애스펙트라는 모듈로 만들어서 설계하고 개발하는 방법을 AOP(Aspect Oriented Programming)이라고 한다
(분리해서 따로 만드는 것을 AOP)
AOP는 새로운 프로그래밍 패러다임이 아니라, OOP를 돕는 보조적인 기술이다
어플리케이션의 핵심기능을 따라 코딩하지 않고, 핵심기능 대신, 부가적인 기능을 바라보고 집중해서 설계하고 개발할 수 있다. (관점지향)
(소설에서도 1인칭 시점 3인칭시점처럼 공통코드 지향으로 본다. 관점지향이라는 것)
스프링이 제공하는 AOP는 프록시를 이용한다
프록시를 통해 타겟 오브젝트의 메소드가 호출될 경우, 프록시(조교같은 역할)가 제어를 가로채고, InvocationHandler와 같은 오브젝트를 통해 타겟 메소드의 실행 전 후로 부가적인 기능을 실행한다
(프록시가 현재 함수가 호출됐는지 안 됐는지 확인을 하는 것 타켓클래스에서 어떤 함수가 호출됐는지 확인하고 삽입을 시켜주는 제어권을 가지고 삽입시켜준다.)
AOP 기술의 원조인 AspectJ는 프록시를 사용하지 않는 대표적인 AOP 기술이다
타깃 오브젝트를 뜯어고쳐서 부가기능을 직접 넣어주는 방식을 사용한다
소스코드를 고치는 것이 아니라, 컴파일 된 타깃 클래스의 파일 자체를 수정하거나 클래스가 JVM에 로딩되는 시점을 가로채서 바이트코드를 조작 한다
(스프링을 호출할 때만 삽입시킬 수 있다. 함수 호출할 때)
AOP 용어
1. Target : 부가기능을 부여할 대상, 핵심기능이 담긴 클래스
2. Advice : 부가기능을 담은 모듈
언제 공통 관심 기능을 핵심 로직에 적용할 지를 정의
Before, After Returning, After Throwing, Around 등이 있다
3. Joinpoint : Advice를 적용 가능한 지점을 의미
메소드 호출, 필드 값 변경 등
스프링의 프록시 AOP에서 조인 포인트는 메소드의 실행 단계뿐이다
타깃 오브젝트가 구현한 인터페이스의 모든 메소드가 조인 포인트가 된다
(타겟 클래스 안에 들어가있는 클래스는 전부 Joinpoint -- Joinpoint라고 해서 전부 다 삽입? X)
(Joinpoint에서 삽입이 이뤄지는 클래스를 Pointcut)
4. Pointcut : 조인 포인트를 선별하는 기능을 정의한 모듈
가능한 조인 포인트들 중에 실제로 부가기능을 적용할 것들을 선별한다
클래스를 선정하고, 그 안의 메소드를 선정하는 과정을 거친다
실제로 Advice가 적용되는 Joinpoint를 나타낸다
5. Proxy : 클라이언트와 타깃 사이에 존재하면서 부가기능을 제공하는 오브젝트
클라이언트는 타깃을 요청하지만, 클라이언트에게는 DI를 통해 타깃 대신 프록시가 주입된다
클라이언트의 메소드 호출을 대신 받아서 타깃에게 위임하며, 그 과정에서 부가기능을 부여한다
스프링 AOP는 프록시를 이용한다
(보조역할을 해주는)
6. Advisor : 어드바이스와 포인트컷을 하나로 묶어 취급한 것
AOP의 가장 기본이 되는 모듈이다
스프링은 자동 프록시 생성기가 어드바이저 단위로 검색해서 AOP를 적용한다
7. Aspect : 다수의 포인트컷과 어드바이스의 조합으로 만들어진다
보통 싱글톤 형태의 오브젝트로 존재한다
어드바이저는 아주 단순한 애스펙트라고 볼 수 있다
8. Weaving : Advice를 핵심로직코드에 적용하는 것을 Weaving라고 한다.
[실습]
Project : Chapter03_XML
Project : Chapter03_XML Spring Legacy Project
-- configure -- pom.xml(17로 바꾸기 + dependencies 복붙)
pom.xml
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>Chapter03_XML</groupId>
<artifactId>Chapter03_XML</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>17</release>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.37</version>
</dependency>
<!-- AOP -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.22.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.22.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
maven update project하고
build path로 가서 project Facets 17로 바꾸기 + build path 17버전으로 맞추고
Project: Chapter03_ANNO (Maven Project)
pom.xml
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>Chapter03_ANNO</groupId>
<artifactId>Chapter03_ANNO</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.37</version>
</dependency>
<!-- AOP -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.22.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.22.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
자바 버전 바꾸기 build path + project Facets
update maven -- error 떠서 build부분 지우고 upate하고 다시 build 넣으니 된다.
근데 자바 버전이 다시 바뀌니까 다시 17버전으로 바꿔야함.
[ Chapter03_XML ]
Package : sample01
Interface : MessageBean.java
package sample01;
public interface MessageBean {
public void showPrintBefore();
public void viewPrintBefore();
public void display();
}
Class : MessageBeanImpl.java
MessageBeanImpl 빈 생성하기 - setter injection으로
package sample01;
import lombok.Setter;
public class MessageBeanImpl implements MessageBean {
@Setter
private String str;
/*
public void setStr(String str) {
this.str = str;
}
*/
@Override
public void showPrintBefore() {
// TODO Auto-generated method stub
}
@Override
public void viewPrintBefore() {
// TODO Auto-generated method stub
}
@Override
public void display() {
// TODO Auto-generated method stub
}
}
src/main/resources : acQuickStart.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<bean id="messageBeanImpl" class="sample01.MessageBeanImpl">
<property name="str" value="Have a nice day!!"></property>
</bean>
</beans>
MessageBeanImpl.java
package sample01;
import lombok.Setter;
public class MessageBeanImpl implements MessageBean {
@Setter
private String str;
/*
public void setStr(String str) {
this.str = str;
}
*/
@Override
public void showPrintBefore() {
System.out.println("showPrintBefore 메세지 = " + str); //핵심코드
}
@Override
public void viewPrintBefore() {
try {
Thread.sleep(1000);//단위: 1/1000
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("viewPrintBefore 메세지 = " + str );
}
@Override
public void display() {
System.out.println("display 메세지 = " + str);
}
}
다들 핵심코드만 가지고 있는 상태인데
여기서 공통코드를 삽입하려한다. --- showPrintBefore() / viewPrintBefore()
display()에는 넣지 않는다.
공통코드가 들어갈 함수를 따로 잡겠다는 것이다.
LoggingAdvice.java - 공통관심사항
package sample01;
//공통관심사항
public class LoggingAdvice {
public void beforeTrace() {
System.out.println("before trace");
}
}
이제 삽입시키겠다.
먼저 빈 생성해야한다.
MessageBeanImpl이 타겟이다. 이 클래스 안에 삽입시키기 때문에 Target 클래스라 한다.
showPrintBefore / viewPrintBefore / display -- joinPoint (얘네들이 대상자)
showPrintBefore / viewPrintBefore -- pointCut(공통코드가 대상자)
함수 실행될 때만 일어난다는 뜻 -- execution()
만약에 public void / public int 이런식으로 있으면 execution(public void * ~~~)
execution(public void sample01.MessageBeanImpl) 이렇게 하면 display가 안빠지므로
execution(public void sample01.MessageBeanImpl.*Before())
이런식으로 Before로 끝나는 함수들만 고르게 되는 것 !
public void showPrintBefore (int a, int b)
public void viewPrintBefore (String a)
이런식으로 매개변수가 다르게 들어가면 .. 을 붙여주면 된다.
execution(public void sample01.MessageBeanImpl.*Before(..))
<aop:pointcut expression="" id=""/> 이건 여러개가 들어가도 된다. 그러므로 구분할 id명 적어줘야한다.
id="beforeMethod"
<aop:aspect> -- 공통코드는 무엇인지 누가쥐고 있는지 알려줘야한다.
method="beforeTrace" -- 어떤 메소드 집어넣을건지
pointcut-ref="beforeMethod" -- 어디에 집어넣을건지
acQuickStart.xml
<!-- AOP -->
<aop:config>
<aop:pointcut
expression="execution(public void sample01.MessageBeanImpl.*Before())"
id="beforeMethod"/>
<aop:aspect ref="LoggingAdvice">
<aop:before method="beforeTrace" pointcut-ref="beforeMethod"/>
</aop:aspect>
</aop:config>
HelloSpring.java
package sample01;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloSpring {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("acQuickStart.xml");
MessageBean messageBean = (MessageBean) context.getBean("messageBeanImpl");
messageBean.showPrintBefore();
}
}
package sample01;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloSpring {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("acQuickStart.xml");
MessageBean messageBean = (MessageBean) context.getBean("messageBeanImpl");
messageBean.showPrintBefore();
System.out.println();
messageBean.viewPrintBefore();
System.out.println();
messageBean.display();
}
}
HelloSpring.java -- after에 찍어보기
package sample01;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloSpring {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("acQuickStart.xml");
MessageBean messageBean = (MessageBean) context.getBean("messageBeanImpl");
/*
System.out.println("*** Before ***");
messageBean.showPrintBefore();
System.out.println();
messageBean.viewPrintBefore();
System.out.println();
messageBean.display();
*/
System.out.println("*** After ***");
messageBean.showPrintAfter();
System.out.println();
messageBean.viewPrintAfter();
System.out.println();
messageBean.display();
}
}
MessageBean.java
public void showPrintAfter();
public void viewPrintAfter();
package sample01;
public interface MessageBean {
public void showPrintBefore();
public void viewPrintBefore();
public void showPrintAfter();
public void viewPrintAfter();
public void display();
}
MessageBeanImpl.java
package sample01;
import lombok.Setter;
public class MessageBeanImpl implements MessageBean {
@Setter
private String str;
/*
public void setStr(String str) {
this.str = str;
}
*/
@Override
public void showPrintBefore() {
System.out.println("showPrintBefore 메세지 = " + str); //핵심코드
}
@Override
public void viewPrintBefore() {
try {
Thread.sleep(1000);//단위: 1/1000
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("viewPrintBefore 메세지 = " + str );
}
@Override
public void showPrintAfter() {
System.out.println("showPrintAfter 메세지 = " + str);
}
@Override
public void viewPrintAfter() {
try {
Thread.sleep(1000);//단위: 1/1000
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("viewPrintAfter 메세지 = " + str );
}
@Override
public void display() {
System.out.println("display 메세지 = " + str);
}
}
LoggingAdvice.java
package sample01;
//공통관심사항
public class LoggingAdvice {
public void beforeTrace() {
System.out.println("before trace");
}
public void afterTrace() {
System.out.println("after trace");
}
}
acQuickStart.xml
<!-- AOP -->
<aop:config>
<aop:pointcut
expression="execution(public void sample01.MessageBeanImpl.*Before())"
id="beforeMethod"/>
<aop:pointcut
expression="execution(public void sample01.MessageBeanImpl.*After())"
id="afterMethod"/>
<aop:aspect ref="loggingAdvice">
<aop:before method="beforeTrace" pointcut-ref="beforeMethod"/>
<aop:after method="afterTrace" pointcut-ref="afterMethod"/>
</aop:aspect>
</aop:config>
public * *.*.*After(..)
이런식으로 별잔치로 해도된다.
HelloSpring.java -- 앞 뒤로 끼게 하기
System.out.println("*** Around ***");
messageBean.showPrint();
System.out.println();
messageBean.viewPrint();
System.out.println();
messageBean.display();
MessageBean.java
package sample01;
public interface MessageBean {
public void showPrintBefore();
public void viewPrintBefore();
public void showPrintAfter();
public void viewPrintAfter();
public void showPrint();
public void viewPrint();
public void display();
}
MessageBeanImpl.java
@Override
public void showPrint() {
System.out.println("showPrint 메세지 = " + str);
}
@Override
public void viewPrint() {
try {
Thread.sleep(1000);//단위: 1/1000
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("viewPrint 메세지 = " + str );
}
LoggingAdvice.java
package sample01;
//공통관심사항
public class LoggingAdvice {
public void beforeTrace() {
System.out.println("before trace");
}
public void afterTrace() {
System.out.println("after trace");
}
public void Trace() {
System.out.println("입실");
System.out.println("퇴실");
}
}
arround는 수행순서가 좀 까다롭다.
public void Trace() {
1. System.out.println("입실"); 수행하고
2. 핵심코드를 수행하는 메소드를 호출한다.
3. System.out.println("퇴실"); 수행하기
}
위와 같은 방식으로 되어야한다.
pom.xml
<!--<scope>runtime</scope> --> 주석처리하기
<!-- AOP -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.22.1</version>
<!--<scope>runtime</scope> -->
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.22.1</version>
<scope>runtime</scope>
</dependency>
LoggingAdvice.java
package sample01;
import org.aspectj.lang.ProceedingJoinPoint;
//공통관심사항
public class LoggingAdvice {
public void beforeTrace() {
System.out.println("before trace");
}
public void afterTrace() {
System.out.println("after trace");
}
public void trace(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("입실");
joinPoint.proceed();//핵심코드를 수행하는 메소드를 호출한다.
System.out.println("퇴실");
}
}
acQuickStart.xml
<!-- AOP -->
<aop:config>
<aop:pointcut
expression="execution(public void sample01.MessageBeanImpl.*Before())"
id="beforeMethod"/>
<aop:pointcut
expression="execution(public * *.*.*After())"
id="afterMethod"/>
<aop:pointcut
expression="execution(public * *.MessageBeanImpl.*Print(..))"
id="aroundMethod"/>
<aop:aspect ref="loggingAdvice">
<aop:before method="beforeTrace" pointcut-ref="beforeMethod"/>
<aop:after method="afterTrace" pointcut-ref="afterMethod"/>
<aop:around method="trace" pointcut-ref="aroundMethod"/>
</aop:aspect>
</aop:config>
수행시간 계산하기
LoggingAdvice.java
package sample01;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.util.StopWatch;
//공통관심사항
public class LoggingAdvice {
public void beforeTrace() {
System.out.println("before trace");
}
public void afterTrace() {
System.out.println("after trace");
}
public void trace(ProceedingJoinPoint joinPoint) throws Throwable {
/*
System.out.println("입실");
joinPoint.proceed();//핵심코드를 수행하는 메소드를 호출한다.
System.out.println("퇴실");
*/
String methodName = joinPoint.getSignature().toShortString();
System.out.println("메소드 = " + methodName);
StopWatch stopWatch = new StopWatch();
stopWatch.start();
joinPoint.proceed();//핵심코드를 수행하는 메소드를 호출한다.
stopWatch.stop();
System.out.println("처리시간 = " + stopWatch.getTotalTimeMillis()/1000 + "초");
}
}
MessageBean.java
public String showPrint();
package sample01;
public interface MessageBean {
public void showPrintBefore();
public void viewPrintBefore();
public void showPrintAfter();
public void viewPrintAfter();
public String showPrint();
public void viewPrint();
public void display();
}
MessageBeanImpl.java
@Override
public String showPrint() {
System.out.println("showPrint 메세지 = " + str);
return "스프링";
}
[ Chapter03_ANNO ]
acQuickStart.xml -- 다 지우고
<aop:aspectj-autoproxy />
<context:component-scan base-package="sample01" />
추가하기
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<context:component-scan base-package="sample01" />
</beans>
MessageBeanImpl.java
@Component
롬복 걷어내기
private String str;
@Autowired
public void setStr(@Value("Have a nice day!!")String str) {
this.str = str;
}
@Component
public class MessageBeanImpl implements MessageBean {
private String str;
@Autowired
public void setStr(@Value("Have a nice day!!")String str) {
this.str = str;
}
LoggingAdvice.java
@Aspect -- 공통으로 들어간다.
@Component
@Before("execution(public void sample01.MessageBeanImpl.*Before())")
@After("execution(public * *.*.*After())")
@Around("execution(public * *.MessageBeanImpl.*Print(..))")
package sample01;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
//공통관심사항
@Aspect
@Component
public class LoggingAdvice {
@Before("execution(public void sample01.MessageBeanImpl.*Before())")
public void beforeTrace() {
System.out.println("before trace");
}
@After("execution(public * *.*.*After())")
public void afterTrace() {
System.out.println("after trace");
}
@Around("execution(public * *.MessageBeanImpl.*Print(..))")
public void trace(ProceedingJoinPoint joinPoint) throws Throwable {
/*
System.out.println("입실");
joinPoint.proceed();//핵심코드를 수행하는 메소드를 호출한다.
System.out.println("퇴실");
*/
String methodName = joinPoint.getSignature().toShortString();
System.out.println("메소드 = " + methodName);
StopWatch stopWatch = new StopWatch();
stopWatch.start();
Object ob = joinPoint.proceed();//핵심코드를 수행하는 메소드를 호출한다.
System.out.println("반환값 = " + ob);
stopWatch.stop();
System.out.println("처리시간 = " + stopWatch.getTotalTimeMillis()/1000 + "초");
}
}
HelloSpring.java
package sample01;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloSpring {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("acQuickStart.xml");
MessageBean messageBean = (MessageBean) context.getBean("messageBeanImpl");
/*
System.out.println("*** Before ***");
messageBean.showPrintBefore();
System.out.println();
messageBean.viewPrintBefore();
System.out.println();
messageBean.display();
*/
/*
System.out.println("*** After ***");
messageBean.showPrintAfter();
System.out.println();
messageBean.viewPrintAfter();
System.out.println();
messageBean.display();
*/
System.out.println("*** Around ***");
messageBean.showPrint();
System.out.println();
messageBean.viewPrint();
System.out.println();
messageBean.display();
}
}
[ SpringConfiguration ]
@Component 주석걸기
acQuickStart.xml
<context:component-scan base-package="spring.conf" />
Package: spring.conf
SpringConfiguration.java
@Configuration
@EnableAspectJAutoProxy
package spring.conf;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
public class SpringConfiguration {
}
MessageBeanImpl / LoggingAdvice - @Bean 생성
package spring.conf;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import sample01.LoggingAdvice;
import sample01.MessageBeanImpl;
@Configuration
@EnableAspectJAutoProxy
public class SpringConfiguration {
@Bean
public MessageBeanImpl messageBeanImpl() {
return new MessageBeanImpl();
}
@Bean
public LoggingAdvice loggingAdvice() {
return new LoggingAdvice();
}
}
'Spring' 카테고리의 다른 글
DAY 64 - 스프링 프레임워크 MVC (2024.10.07) (0) | 2024.10.07 |
---|---|
DAY 63 - 스프링 프레임워크 - JDBC / HOMEWORK (2024.10.04) (2024.10.07) (1) | 2024.10.04 |
DAY 62 - 스프링 프레임워크 - 파일출력 (2024.10.02) (1) | 2024.10.02 |
DAY 61 - 스프링 프레임워크 HOMEWORK (2024.10.01) (2024.10.02) (0) | 2024.10.02 |
DAY 61 - 스프링 프레임워크 (2024.10.01) (1) | 2024.10.01 |