열심히 끝까지
디바이스 융합 자바(Java) day67(1) - 바인드 변수, joinPoint 본문
디바이스 융합 자바(Java) day67(1) - 바인드 변수, joinPoint
노유림 2022. 9. 16. 11:52[ 지난 수업 ]
Spring 프레임워크
: 유지보수를 위해 사용
- IoC와 AOP를 지원하는 경량의 프레임워크 덕분
> 제어의 역행(IoC)
: 의존관계
- 어떤 객체가 특성메서드를 수행할 때에 다른 객체를 사용하는 것(멤버변수)
ex ) 캐릭터 - 무기, 폰 - 워치, C(Service) - DAO, ....
: 의존성주입(DI)
- new 결합도를 높히는 코드
- 결합도를 낮추기 위해 컨테이너에게 부탁함
.xml @
<bean> @Component
생성자인젝션 @Autowired
setter인젝션
> 관점지향 프로그래밍
우선 두 개로 분리
- CRUD(비즈니스메서드, 핵심로직)
- 횡단관심(공통로직)
: 어떤 핵심로직 + 횡단관심을 엮을지를 스프링 컨테이너에게 알려주어야 함!
: .xml, @으로 설정 가능
※ Advice
: 횡단관심
<bean id="logAdvice" class="com.ryo.biz.common.LogAdvice" />
※ pointcut
: 횡단관심과 엮일 핵심로직
<aop:pointcut expression="execution(* com.ryo.biz..*Impl.*(..))" id="aPointcut"/>
※ aspect
: 횡단관심 + 포인트컷 의 "결합"을 의미
: 시점이 필요 -> before, after, around, ...
<aop:aspect ref="logAdvice">
<aop:before method="printLog" pointcut-ref="aPointcut"/>
</aop:aspect>
-------------------------------------------------------------------------------------------
[오늘 수업]
[ JoinPoint | 바인드 변수 ]
- 바인딩
ex)
상위 추상클래스 포켓몬
: 추상 메서드 정의 가능
하위 클래스 피카츄 / 바이리 / 꼬부기
: 추상메서드를 반드시 재정의해야함(강제)
이때, 포켓몬 배열 생성
포켓몬[] datas={new 피카츄(), ...};
datas[0] hello(); = 피카피카
>> 이 것을 바인딩 되었다고 함
>> 상위 클래스의 메서드가 호출되는 것이 아니라,
하위 클래스의 메서드가 호출되는 현상
== 동적 바인딩 => 다형성 실현 예시
" 현재 메서드를 수행하는 실제 [주체]가 누구인지"
-> 객체
-----------------------------
>> 횡단관심이 좀 더 의미를 가지려면,
현재 수행중인 비즈니스 메서드가 무엇인지 파악하는 것이 좋음
※ joinPoint(조인포인트)
: 수행중인 포인트컷
ex ) AroundAdvice에 pjp가 인자이기 때문에
현재 진행중인 비즈니스 메서드를 파악할 수 있고
돌려주는 것이 있기 때문에 Object라는 반환값을 가짐
: joinpoint를 인자로 가지게 되면(pjp처럼) 현재 수행중인 비즈니스 메서드의 시그니처 등을 알 수 있음
>> 비즈니스 메서드 시그니처 ex ) CRUD 인자, Output 등
ex ) -----------------------------------------------------
-----------------LogAdvice.java
package com.ryo.biz.common;
import org.aspectj.lang.JoinPoint;
public class LogAdvice {
public void printLog(JoinPoint jp) {
// 인자로 joinpoint 제공(=aspectj 통해 import)
// output == signature
// getName() == 현재 수행중인 포인트컷(핵심로직, CRUD)의 메서드명
String methodName=jp.getSignature().getName();
// output == object 어떤 것이든 다 뱉음
Object[] args=jp.getArgs();
System.out.println("수행중인 핵심메서드명 : " + methodName);
System.out.println("사용하는 인자");
// 오버라이딩 + 동적바인딩
for(Object v : args) {
System.out.println(v);
}
// System.out.println(">>> 공통로직 <<< 핵심로직 수행 전에 호출됨");
}
}
-----------------applicationContext.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"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
<context:component-scan base-package="com.ryo.biz" />
<bean id="logAdvice" class="com.ryo.biz.common.LogAdvice" />
<aop:config>
<aop:pointcut expression="execution(* com.ryo.biz..*Impl.*(..))" id="aPointcut"/>
<aop:aspect ref="logAdvice">
<aop:before method="printLog" pointcut-ref="aPointcut"/>
</aop:aspect>
</aop:config>
</beans>
--------------------결과
>> ++++++++++뒤로 인자 뜨고 ===========로 종료
>> 다른 예시
-----------------AfterReturningAdvice.java(값을 돌려주는 advice)
package com.ryo.biz.common;
import org.aspectj.lang.JoinPoint;
import com.ryo.biz.member.MemberVO;
public class AfterReturningAdvice {
public void printLogAfterReturning(JoinPoint jp, Object returnObj) {
String methodName=jp.getSignature().getName();
Object[] args=jp.getArgs();
System.out.println("수행중인 핵심 메서드 명 : " + methodName);
System.out.println("사용하는 인자");
System.out.println("++++");
for(Object v : args) {
System.out.println(v);
}
System.out.println("====");
if(returnObj instanceof MemberVO) {
MemberVO mvo = (MemberVO)returnObj;
if(mvo.getRole().equals("ADMIN")) {
System.out.println("관리자입니다.");
}
else {
System.out.println("일반계정입니다.");
}
}
System.out.println("핵심메서드의 반환값 : " + returnObj);
}
}
-----------------AfterThrowingAdvice.java(예외시 던지는 advice)
package com.ryo.biz.common;
import org.aspectj.lang.JoinPoint;
public class AfterThrowingAdvice {
public void printLogAfterThrowing(JoinPoint jp, Exception exceptObj) {
String methodName=jp.getSignature().getName();
Object[] args=jp.getArgs();
System.out.println("수행중인 핵심 메서드 명 : " + methodName);
System.out.println("사용하는 인자");
System.out.println("++++");
for(Object v : args) {
System.out.println(v);
}
System.out.println("====");
// 약식(이런 형태로 사용 가능)
System.out.println("발생한 예외" + exceptObj.getMessage());
if(exceptObj instanceof IllegalArgumentException) {
System.out.println("올바르지 않은 인자값을 사용했습니다...");
}
else if(exceptObj instanceof NumberFormatException) {
System.out.println("숫자 형식이 아닌 값을 사용했습니다...");
}
else if(exceptObj instanceof Exception) {
System.out.println("예외가 발생했습니다...");
}
else {
System.out.println("확인되지 않은 에러가 발생했습니다!!!");
}
}
}
-----------------AroundAdvice.java(시간 측정 advice)
package com.ryo.biz.common;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.util.StopWatch;
// around로 사용할 advice는 반드시 pjp를 input으로 가져야한다!!!
public class AroundAdvice { // 본인이 핵심메서드를 수행하게 해야 함
public Object printLogAround(ProceedingJoinPoint pjp) throws Throwable {
String methodName=pjp.getSignature().getName();
System.out.println("수행중인 핵심 메서드 명 : " + methodName);
StopWatch sw = new StopWatch();
// 시간을 측정하는 메서드 == spring 제공
sw.start();
Object returnObj=pjp.proceed(); // 수행해야할 포인트컷
sw.stop();
System.out.println("수행시간 : " + sw.getTotalTimeMillis()+"ms");
return returnObj;
}
}
-----------------applicationContext.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"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
<context:component-scan base-package="com.ryo.biz" />
<bean id="ara" class="com.ryo.biz.common.AfterReturningAdvice" />
<bean id="ata" class="com.ryo.biz.common.AfterThrowingAdvice" />
<bean id="aa" class="com.ryo.biz.common.AroundAdvice" />
<!--
<bean id="logAdvice" class="com.ryo.biz.common.LogAdvice" />
<bean id="logSelectAdvice" class="com.ryo.biz.common.LogSelectAdvice" />
<bean id="aroundAdvice" class="com.ryo.biz.common.AroundAdvice" />
-->
<aop:config>
<aop:pointcut expression="execution(* com.ryo.biz..*Impl.*(..))" id="aPointcut"/>
<aop:pointcut expression="execution(* com.ryo.biz..*Impl.select*(..))" id="bPointcut"/>
<!--
<aop:pointcut expression="execution(* com.ryo.biz..*Impl.select*(..))" id="bPointcut"/>
<aop:pointcut expression="execution(* com.ryo.biz..*Impl.*(..))" id="cPointcut"/>
-->
<aop:aspect ref="aa">
<aop:around method="printLogAround" pointcut-ref="aPointcut"/>
</aop:aspect>
<aop:aspect ref="ara">
<aop:after-returning method="printLogAfterReturning" pointcut-ref="bPointcut" returning="returnObj"/>
</aop:aspect>
<aop:aspect ref="ata">
<aop:after-throwing method="printLogAfterThrowing" pointcut-ref="bPointcut" throwing="exceptObj"/>
</aop:aspect>
<!--
<aop:aspect ref="logAdvice">
<aop:before method="printLog" pointcut-ref="aPointcut"/>
</aop:aspect>
<aop:aspect ref="logSelectAdvice">
<aop:before method="printLogSelect" pointcut-ref="bPointcut"/>
</aop:aspect>
<aop:aspect ref="aroundAdvice">
<aop:around method="printLogAround" pointcut-ref="cPointcut"/>
</aop:aspect>
-->
</aop:config>
</beans>
-----------MemberService.java
package com.ryo.biz.member.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ryo.biz.member.MemberService;
import com.ryo.biz.member.MemberVO;
@Service("memberService")
public class MemberServiceImpl implements MemberService {
@Autowired // MemberDAO 타입
private MemberDAO memberDAO; // 핵심로직을 수행할 객체
@Override
public void insertMember(MemberVO vo) {
memberDAO.insertMember(vo);
}
@Override
public MemberVO selectOneMember(MemberVO vo) {
if(vo.getMid().equals("timo")) {
throw new IllegalArgumentException("[실행시예외]");
}
return memberDAO.selectOneMember(vo);
}
@Override
public void updateMember(MemberVO vo) {
memberDAO.updateMember(vo);
}
@Override
public void deleteMember(MemberVO vo) {
memberDAO.deleteMember(vo);
}
}
>> 일부러 예외를 발생시키기 위해 memberservice에 예외 처리
---------------------결과
'디바이스 융합 자바(Java)기반 풀스택 개발자 양성과정(수업내용)' 카테고리의 다른 글
디바이스 융합 자바(Java) day68 - Spring에서의 MVC2 패턴 (1) | 2022.09.19 |
---|---|
디바이스 융합 자바(Java) day67(2) - 바인드 변수, Jdbc Template (0) | 2022.09.16 |
디바이스 융합 자바(Java) day66(2) - AOP 관련 용어정리 및 예시 (0) | 2022.09.15 |
디바이스 융합 자바(Java) day66(1) - 9/14과제 설명, AOP(Advice) (0) | 2022.09.15 |
디바이스 융합 자바(Java) day65(2) - 스프링(@(어노테이션),컴포넌트(@Component),@Repository,@Service) (1) | 2022.09.14 |