※ 복습
강력한 4가지 특징 중 2가지를 배움
Spring web을 하게 되었을 때 컨트롤러 서비스 래퍼 등 사전에 배워야 할 것들을 배우고 잇음.
※ 수업
AspectJ 포인트 컷 표현식을 화용한 포인트 컷
JDK 정규식보다 많이 사용되며
AspectJExpressionPointcut클래스를 제공,
aspectjrt.jar, aspectjweaver.jar 두 라이브러리 파일이 필요함.
라이브러리 추가
https://mvnrepository.com/artifact/org.aspectj/aspectjrt/1.9.19
https://mvnrepository.com/artifact/org.aspectj/aspectjweaver/1.9.19
예제) aop3
package aop.aop3;
import org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor;
import org.springframework.aop.framework.ProxyFactory;
public class AspectJMain {
public static void main(String[] args) {
First first = new First();
Second second = new Second();
first.one();
first.two();
second.one();
second.two();
System.out.println("==================");
AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor();
advisor.setAdvice(new SimpleAdv());
// AspectJ식 표현식을 사용하게됨
advisor.setExpression("execution(* one(..))");
ProxyFactory pf = new ProxyFactory();
pf.addAdvisor(advisor);
pf.setTarget(first);
First first2 = (First)pf.getProxy();
pf = new ProxyFactory();
pf.addAdvisor(advisor);
pf.setTarget(second);
Second second2 = (Second)pf.getProxy();
first2.one();
first2.two();
second2.one();
second2.two();
}
}
실행 결과
First.one()
First.two()
Second.one()
Second.two()
==================
전처리
First.one()
후처리
First.two()
전처리
Second.one()
후처리
Second.two()
==================
위 예제에서 execution("execution(* one(..))")은 AspectJ식 표현식이다. (가장 많이 활용할 예정)
*은 반환타입
그 옆은 메서드 명
.. 은 파라미터 갯수제한이 없다는 뜻이다.
※ 선언적 AOP 설정
* bean을 등록하기 위한 설정 2가지
xml을 통한 방법
컴포넌트 스캔을 써서 탐색을 시킴
선언적 AOP라는것은 xml에 정의한다는 뜻 (위와 목적이 비슷)
전역설정이다.
어플리케이션 설정에서 어드바이스 적용 프록시를 생성하고 이를 타겟빈에 주입할 수 있는 서비스를 제공
- ProxyFactoryBean을 사용 : 스프링 애플리케이션 컨텍스트를 선언적으로 선언하여 빈 정의를 기반으로 aop프록시를 생성한다
- Spring aop 네임스페이스 : aop 네임스페이스를 이용하여 애스펙트 및 di요구사항을 간단히 정의, aop네임스페이스도 내부적으로 프록시팩토리빈을 사용한다
- @AspectJ Annotation : @AspectJ방식의 어노테이션을 사용하여 클래스 내에서 aop설정이 가능하다.
1. ProxtFactoryBean 사용
- 익명의 빈을 사용, 어플리케이션이 어드바이스 적용 대상이 아닌 ㅅ빈에 실수로 접근하는것을 막을 수 있다 (캡슐화)
1-1 AOP 프록시를 생성하기 위한 ProxyFactoryBean 사용
- IoC컨테이너를 사용한다면 그리고 사용해야한다면 AOP FactoryBean중 하나를 사용하기 원할것이다
Spring AOP 프록시를 생성하는 기본 방법은 org.srpringframework.aop.framework.ProxyFactoryBean을 사용하는 것
이것은 적용할 pointcut과 advice의 완벽한 제어능력을 부여한다.
proxtInterfaces는 사용안함
interceptorNames는 가장 중요, 순서를 의미함
예제)
package aop.aop4;
public class MyDependency {
public void hello() {
System.out.println("hello");
}
public void bye() {
System.out.println("bye");
}
}
package aop.aop4;
import lombok.Setter;
public class MyBean {
@Setter
private MyDependency dependency;
public void run() {
dependency.hello();
dependency.bye();
}
}
package aop.aop4;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class MyAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(method.getName() + "에 대해 before()");
}
}
package aop.aop4;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyMain {
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("aop4.xml");
MyBean myBean = (MyBean)ctx.getBean("myBean");
MyBean myBean1 = (MyBean)ctx.getBean("myBean1");
MyBean myBean2 = (MyBean)ctx.getBean("myBean2");
System.out.println("=============== target ===============");
myBean.run();
System.out.println("=============== advice 적용 ===============");
myBean1.run();
System.out.println("=============== advisor 적용 ===============");
myBean2.run();
ctx.close();
}
}
<?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 class="aop.aop4.MyDependency" id="myDependency" />
<bean class="aop.aop4.MyBean" id="myBean">
<property name="dependency" ref="myDependency"/>
</bean>
<bean class="aop.aop4.MyBean" id="myBean1">
<property name="dependency" ref="proxy1"/>
</bean>
<bean class="aop.aop4.MyBean" id="myBean2">
<property name="dependency" ref="proxy2"/>
</bean>
<!-- advice -->
<bean class="aop.aop4.MyAdvice" id="myAdvice" />
<!-- advisor -->
<bean class="org.springframework.aop.support.DefaultPointcutAdvisor" id="myAdvisor">
<!-- advice -->
<property name="advice" ref="myAdvice"></property>
<!-- pointcut -->
<property name="pointcut">
<bean class="org.springframework.aop.aspectj.AspectJExpressionPointcut">
<property name="expression" value="execution(* hello*(..))" />
</bean>
</property>
</bean>
<!-- proxy 생성 target타입으로 칼같이 적용됨 -->
<bean class="org.springframework.aop.framework.ProxyFactoryBean" id="proxy1">
<property name="interceptorNames">
<list>
<value>myAdvice</value>
</list>
</property>
<!-- target 설정 -->
<property name="target" ref="myDependency" />
</bean>
<!-- advisor에 대한 proxy 생성 -->
<bean class="org.springframework.aop.framework.ProxyFactoryBean" id="proxy2">
<property name="interceptorNames">
<list>
<value>myAdvisor</value>
</list>
</property>
<!-- target 설정 -->
<property name="target" ref="myDependency" />
</bean>
</beans>
실행결과
=============== target ===============
hello
bye
=============== advice 적용 ===============
hello에 대해 before()
hello
bye에 대해 before()
bye
=============== advisor 적용 ===============
hello에 대해 before()
hello
bye
=========================================
예제2) smallMart
package aop.small3;
import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInterceptor;
import org.springframework.aop.Advisor;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.StaticMethodMatcherPointcut;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SmallMartApp {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("small3.xml");
SmallMart mart = (SmallMart)ctx.getBean("smallMart");
mart.getProduct("츄르");
mart.getProduct2("사료");
System.out.println("===============");
SmallMart mart1 = (SmallMart)ctx.getBean("smallMart1");
mart1.getProduct("츄르");
mart1.getProduct2("사료");
System.out.println("===============");
SmallMart mart2 = (SmallMart)ctx.getBean("smallMart2");
mart2.getProduct("캣타워");
mart2.getProduct2("사료");
ctx.close();
}
}
<?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 class="aop.small3.SmallMartImpl" id="smallMart" />
<bean class="aop.small3.BeforeLoggingAdv" id="advice" />
<bean class="aop.small3.AfterLoggingAdv" id="advice2" />
<!-- <bean class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor" id="pointcutAdvisor">
<property name="advice" ref="advice" />
<property name="expression" value="execution(* *2(..))" />
</bean> -->
<bean class="org.springframework.aop.aspectj.AspectJExpressionPointcut" id="pc">
<property name="expression" value="execution(* *2(..))"></property>
</bean>
<bean class="org.springframework.aop.support.DefaultPointcutAdvisor" id="advisor">
<property name="advice" ref="advice" />
<property name="pointcut" ref="pc" />
</bean>
<bean class="org.springframework.aop.framework.ProxyFactoryBean" id="smallMart1">
<property name="interceptorNames">
<list>
<value>advice</value>
</list>
</property>
<property name="target" ref="smallMart"></property>
</bean>
<bean class="org.springframework.aop.framework.ProxyFactoryBean" id="smallMart2">
<property name="interceptorNames">
<list>
<value>pointcutAdvisor</value>
<value>advice2</value>
</list>
</property>
<property name="target" ref="smallMart"></property>
</bean>
</beans>
*read
에제)byte기반 outputStream
package aop.small3;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
public class ReaderTest {
public static void main(String[] args) throws IOException {
// ascii code 입력(아스키로 해석함)
byte[] bytes = {65, 66, 67, 68, 97, 98, 99, 48, 49, 50};
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
BufferedInputStream bis = new BufferedInputStream(bais);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("abcd.txt"), 5);
int i = 0;
byte[] readUnit = new byte[5];
i = bis.read(readUnit);
bos.write(readUnit);
i = bis.read(readUnit);
bos.write(readUnit);
// read는 1byte 씩 읽음 / -1는 더이상 읽을것이 없을 때 출력
// 인덱스를 몇개 읽었는지 출력
// i = bis.read(readUnit);
// 몇번 인덱스부터, 몇개까지 읽는다
// i = bis.read(readUnit, 1, 2);
System.out.println(Arrays.toString(readUnit));
System.out.println(i);
// close 사용하는게 좋다.
// bos.flush();
bos.close();
}
}
보조스트림 사용시 Buffered가 붙은 애들을 적절히 사용해주면 편하게 사용할 수 있다.
※ AOP namespace
1. aop 네임스페이스 사용
- beans태그 내에 aop 네임스페이스를 선언해야 한다.
예제)
package aop.aop5;
public class MyDependency {
public void hello(int intValue) {
System.out.println("hello : " + intValue);
}
public void bye() {
System.out.println("bye");
}
}
package aop.aop5;
import lombok.Setter;
public class MyBean {
@Setter
private MyDependency dependency;
public void run() {
dependency.hello(5500);
dependency.hello(4500);
dependency.bye();
}
}
package aop.aop5;
import org.aspectj.lang.JoinPoint;
public class MyAdvice {
public void simple(JoinPoint joinPoint, int intValue) {
// intValue값이 5000 이상일때 advice 실행
if(intValue > 5000) {
System.out.println("advice 적용 :: " + joinPoint.getSignature().getName() + " : " + intValue);
}
}
}
package aop.aop5;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyMain {
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("aop5.xml");
MyBean myBean = (MyBean)ctx.getBean("myBean");
myBean.run();
ctx.close();
}
}
<?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: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/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<bean class="aop.aop5.MyDependency" id="myDependency" />
<bean class="aop.aop5.MyBean" p:dependency-ref="myDependency" id="myBean" />
<bean class="aop.aop5.MyAdvice" id="myAdvice" />
<aop:config>
<aop:aspect ref="myAdvice">
<aop:pointcut expression="execution(* hello(..)) and args(intValue)" id="pc"/>
<aop:before method="simple" pointcut-ref="pc"/>
<aop:after-returning method="simple" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>
</beans>
'Spring > Spring' 카테고리의 다른 글
23-04-27 Spring (Spring Web Security) (0) | 2023.04.27 |
---|---|
23-03-29 Spring (0) | 2023.03.30 |
23-03-22 Spring (0) | 2023.03.22 |
23-03-21 Spring 비밀글 (0) | 2023.03.21 |
23-03-17 Spring (0) | 2023.03.17 |