ProxyFactoryBean
package site.levinni.aop3;
MyDependency.java
package site.levinni.aop3;
public class MyDependency {
public void hello() {
System.out.println("hello");
}
public void goodbye() {
System.out.println("bye");
}
}
advice가 적용될 곳.
advisor는 hello()만 특정 되게 할 것.
MyBean.java
package site.levinni.aop3;
import lombok.Setter;
@Setter
public class MyBean {
private MyDependency dependency;
public void run() {
dependency.hello();
dependency.goodbye();
}
}
MyBefore.java
package site.levinni.aop3;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class MyBefore implements MethodBeforeAdvice{
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("사전충고");
}
}
MyApp.java
package site.levinni.aop3;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyApp {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("my.xml");
ctx.getBean("myBean1", MyBean.class).run(); // advice
ctx.getBean("myBean2", MyBean.class).run(); // advisor
}
}
my.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="site.levinni.aop3.MyBefore" id="myBefore"></bean>
<bean class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor" id="pointcutAdvisor">
<property name="advice" ref="myBefore"/>
<property name="expression" value="execution(* hello(..))"></property>
</bean>
<bean class="site.levinni.aop3.MyBean" id="myBean1">
<property name="dependency">
<bean class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<bean class="site.levinni.aop3.MyDependency"></bean>
</property>
<property name="interceptorNames">
<list>
<value>myBefore</value>
</list>
</property>
</bean>
</property>
</bean>
<bean class="site.levinni.aop3.MyBean" id="myBean2">
<property name="dependency">
<bean class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<bean class="site.levinni.aop3.MyDependency"></bean>
</property>
<property name="interceptorNames">
<list>
<value>pointcutAdvisor</value>
</list>
</property>
</bean>
</property>
</bean>
</beans>
dependency는 ProxyFactoryBean을 통해 가짜 객체를 만들 것이고 그 대상(target)은 class=MyDependency가 됨.
interceptorNames는 이름값만으로 가져옴.
그 value 값을 가져오기 위해 myBefore빈 생성.
myBean2는 Advisor (어드바이스 + 포인트컷) 적용.
execution(* hello(..)) : "헬로우"이름 딱 지정. (..) 말고 ()는 파라미터 없는 것.
AOP 네임스페이스
선언적인 스프링 AOP 설정을 간단하게 해 줌.
aop 네임스페이스 선언.
모든 스프링 aop 설정을 <aop:config></aop:config> 안에 넣어야 하는데 포인트컷, 애스펙트, 어드바이저 등을 정의하고 다른 스프링 빈을 참조 가능함.
package site.levinni.aop4;
MyDependency.java
package site.levinni.aop4;
public class MyDependency {
public void hello(int val) {
System.out.println("hello :: " + val);
}
public void goodbye() {
System.out.println("bye");
}
}
MyBean.java
package site.levinni.aop4;
import lombok.Setter;
@Setter
public class MyBean {
private MyDependency dependency;
public void run() {
dependency.hello(5200);
dependency.hello(4800);
dependency.goodbye();
}
}
MyAdvice.java
package site.levinni.aop4;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
public class MyAdvice {
public void customBefore(JoinPoint joinPoint, int val) {
if(val > 5000) {
System.out.println("사전충고 실행");
}
}
public Object customAround(ProceedingJoinPoint pjp, int val) throws Throwable {
if(val < 5000) {
System.out.println("주변충고 전처리");
}
return pjp.proceed();
}
}
before advice는 리턴 안 해도 됨. around advice는 리턴 값 필요.
befor advice는 반드시 Joinpoint 타입 인자 필요하고, around advice는 ProceedingJoinPoint 인자 필요!!
MyApp.java
package site.levinni.aop4;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyApp {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("aop4.xml");
ctx.getBean("myBean", MyBean.class).run(); // advice
}
}
aop4.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"
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.2.xsd">
<bean class="site.levinni.aop4.MyBean" id="myBean">
<property name="dependency">
<bean class="site.levinni.aop4.MyDependency"></bean>
</property>
</bean>
<bean class="site.levinni.aop4.MyAdvice" id="myAdvice"></bean>
<aop:config>
<aop:pointcut expression="execution(* hello(..)) and args(val)" id="pc"/>
<aop:aspect ref="myAdvice">
<aop:before method="customBefore" pointcut-ref="pc"/>
</aop:aspect>
<aop:aspect ref="myAdvice">
<aop:around method="customAround" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>
</beans>
첫 부분 역시나 익명빈 사용!
pointcut의 표현식 인자가 있으면 and args(매개변수 이름) 해 줘야 함.
package site.levinni.smallmart4;
MyAdvice.java
package site.levinni.smallmart4;
import org.aspectj.lang.JoinPoint;
public class MyAdvice {
public void beforeAdv(JoinPoint jp) {
System.out.println("사전처리맨");
}
}
인터페이스를 구현해서 사용하는 게 아니라 조인포인트를 이용하는 것!!
SmallMart.java
package site.levinni.smallmart4;
public interface SmallMart {
public void getProducts(String productName) throws Exception;
public void getProducts2(String productName) throws Exception;
}
SmallMartImpl.java
package site.levinni.smallmart4;
public class SmallMartImpl implements SmallMart{
@Override
public void getProducts(String productName) throws Exception {
System.out.println(productName + ":: getProducts()");
// throw new Exception("small mart 예외");
}
@Override
public void getProducts2(String productName) throws Exception {
System.out.println(productName + ":: getProducts2()");
}
}
smallmart4.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"
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.2.xsd">
<bean class="site.levinni.smallmart4.SmallMartImpl" id="smallMart"/>
<bean class="site.levinni.smallmart4.MyAdvice" id="myAdvice"/>
<aop:config>
<aop:pointcut expression="execution(* *2(..))" id="pc"/>
<aop:aspect ref="myAdvice">
<aop:before method="beforeAdv" pointcut-ref="pc"/>
<aop:after-returning method="beforeAdv" pointcut-ref="pc"/>
<aop:after method="beforeAdv" pointcut-ref="pc"/>
<aop:after-throwing method="beforeAdv" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>
</beans>
똑같은 메서드로 다른 종류의 충고들을 추가할 수 있음.
어떤 advice를 넣을 것인지 어디에 넣을 것인지!만 기억하자.
pointcut-ref 대신 pointcut만 쓰면 value 값을 나타내는 거니깐,
pointcut-ref="pc"대신에 pointcut="execution(* *))"도 됨!!
SmallMartApp.java
package site.levinni.smallmart4;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SmallMartApp {
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("smallmart4.xml");
SmallMart proxy = ctx.getBean("smallMart", SmallMart.class);
try{
System.out.println("===proxy===");
proxy.getProducts("칫솔");
proxy.getProducts2("치실2");
} catch (Exception e) {
// TODO: handle exception
}
}
}
package site.levinni.smallmart5; (@AspectJ 방식의 Annotation) 제일 많이 씀!
MyAdvice.java
package site.levinni.smallmart5;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Service;
@Aspect @Service
public class MyAdvice {
@Before("execution(* *2(..))")
public void beforeAdv(JoinPoint jp) {
System.out.println("사전처리맨");
}
}
이 클래스에서 모든 걸 다 처리할 것이기 때문에 제일 중요!
SmallMart.java
package site.levinni.smallmart5;
public interface SmallMart {
public void getProducts(String productName) throws Exception;
public void getProducts2(String productName) throws Exception;
}
SmallMartImpl.java
package site.levinni.smallmart5;
import org.springframework.stereotype.Service;
@Service("smallMart")
public class SmallMartImpl implements SmallMart{
@Override
public void getProducts(String productName) throws Exception {
System.out.println(productName + ":: getProducts()");
// throw new Exception("small mart 예외");
}
@Override
public void getProducts2(String productName) throws Exception {
System.out.println(productName + ":: getProducts2()");
}
}
smallmart5.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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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="site.levinni.smallmart5"/>
<aop:aspectj-autoproxy/>
</beans>
aop 네임스페이스 추가!
SmallMartApp.java
package site.levinni.smallmart5;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SmallMartApp {
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("smallmart5.xml");
SmallMart proxy = ctx.getBean("smallMart", SmallMart.class);
try{
System.out.println("===proxy===");
proxy.getProducts("칫솔");
proxy.getProducts2("치실2");
} catch (Exception e) {
// TODO: handle exception
}
}
}
'스프링 Spring' 카테고리의 다른 글
21. 04. 01. (0) | 2021.04.01 |
---|---|
Spring JDBC 21. 03. 31. (0) | 2021.03.31 |
AOP 21. 03. 30. (0) | 2021.03.30 |
IoC 21. 03. 29. (0) | 2021.03.29 |
Spring IoC 및 DI 21. 03. 26. (0) | 2021.03.26 |