2013년 7월 27일 토요일

[오라클자바개발자실무교육,오엔제이프로그래밍실무교육센터,Spring Framework3.2]Spring AOP(스프링 선언적 AOP, FroxyFactoryBean)

Spring IoC컨테이너(ApplicationContext BeanFactory)를 사용한다면 그리고 사용해야 한다면  AOP FactoryBean중 하나를 사용하길 원할 것이다. Spring AOP 프록시를 생성하는 기본 방법은 org.srpringframework.aop.framework.ProxyFactroryBean을 사용하는 것이다.  이것은 적용할 pointcut advice의 완벽한 제어능력을 부여한다.


오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷  실무전문 강의)



  
ProxyFactoryBean 클래스는 빈에 타겟을 지정할 수 있게 해주는 FactoryBean의 구현체로 AOP 프록 시에 적용할 빈의 어드바이스와 어드바이저를 제공한다.
ProxyFactoryBean을 이용하는 경우 어드바이저와 어드바이스를 모두 사용할 수 있으므로 어드바이스 뿐 아니라 포인트컷도 선언적으로 설정 할 수 있다.
타겟을 정하고 ProxyFactoryBean을 사용해 애플리케이션이 접근 할 빈을 정의 후 타겟빈을 프록시 타겟으로 사용한다.가능하다면 타겟빈은 프록시 선언 빈 안에서 익명의 빈으로 정의하여 애플리케이션이 어드바이스 적용 대상이 아닌 빈에 실수로 접근하는 것을 막을 수 있다. 물론 같은 빈에 대해 둘이상의 프록시를 생성해야 하는 경우라면, 이 때는 최상위 레벨 빈을 사용해야 한다.
target
프록시의 대상 빈, 충고를 받을 객체
proxyInterfaces
프록시에 의해 구현돼야 하는 인터페이스 목록
interceptorNames
  • 적용될 충고의 빈이름. 이 특성은 BeanFactory안에서 사용되기 위해 반드시 설정
  • 대상 빈에 적용돼야 하는 충고자나 충고의 목록
  • 이 목록의 순서는 적용될 충고의 순서를 의미하기 때문에 중요하다.
[MyDependency.java]
package onj.edu.aop8;
//충고를 받을 , MyBean setter 주입된다.
public class MyDependency {
       public void hello() {
             System.out.println("hello... OnJ");
       }
       public void goodbye() {
             System.out.println("goodbye... OnJ");
       }
}



[MyBean.java]
package onj.edu.aop8;
//의존객체(MyDependency)를 주입받고 run() 메인에서 호출당함
public class MyBean {
           private MyDependency dependency;
           public void run() {
                     dependency.hello();
                     dependency.goodbye();
           }
           public void setDependency(MyDependency dependency) {
                     this.dependency = dependency;
           }
}
[MyAdvice.java]
package onj.edu.aop8;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
//타겟이 되는 MyDendency hello(), goodbye()에 적용될 충고
public class MyAdvice implements MethodBeforeAdvice {
           public void before(Method method, Object[] args, Object target) throws Throwable{
                     System.out.println("사전 충고 받으시오::" + method);
           }
}
[aop-context8.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:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
             http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-3.2.xsd
             http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
            
             <!-- MyBean 세터를 통해 중고가 적용될 프록시빈이 주입 -->
             <bean id="myBean1" class="onj.edu.aop8.MyBean">
                    <property name="dependency">
                           <ref local="myDependency1"/>
                    </property>
             </bean>
            
             <!-- MyBean 세터를 통해 중고가 적용될 프록시빈이 주입 -->
             <bean id="myBean2" class="onj.edu.aop8.MyBean">
                    <property name="dependency">
                           <ref local="myDependency2"/>
                    </property>
             </bean>     
            
             <!-- 프록시 1(어드바이스를 직접사용해서 타겟에 충고적용, 모든 메소드가 충고 적용) -->
             <bean id="myDependency1" class="org.springframework.aop.framework.ProxyFactoryBean">
                    <property name="target">
                           <ref local="myDependencyTarget"/>
                    </property>
                    <property name="interceptorNames">
                           <list>
                                 <value>advice</value>
                           </list>
                    </property>
             </bean>
            
             <!--  프록시2(AspectJ__EXPRESSION__Pointcut DefaultPointcutAdvisor 설정해 MyDependency hello() 충고 적용 -->
             <bean id="myDependency2" class="org.springframework.aop.framework.ProxyFactoryBean">
                    <property name="target">
                           <ref local="myDependencyTarget"/>
                    </property>
                    <property name="interceptorNames">
                           <list>
                                 <value>advisor</value>
                           </list>
                    </property>
             </bean>            
            
             <bean id="advice" class="onj.edu.aop8.MyAdvice"/>
            
             <!--  실제 충고를 받을 , 이빈이 프록시가 되어 충고가 적용됨 -->
             <bean id="myDependencyTarget" class="onj.edu.aop8.MyDependency"/>
            
             <bean id="advisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
                    <property name="advice">
                           <ref local="advice"></ref>
                    </property>
                    <property name="pointcut">
                        <!--  포인트컷으로 익명 빈을 사용 -->
                           <bean class="org.springframework.aop.aspectj.AspectJ__EXPRESSION__Pointcut">
                                 <property name="__EXPRESSION__">
                                        <value>execution(* hello*(..))</value>
                                 </property>
                           </bean>
                    </property>               
             </bean>                   
</beans>           
[ProxyFactoryBeanExam.java]
package onj.edu.aop8;
import org.springframework.context.support.GenericXmlApplicationContext;
public class ProxyFactoryBeanExam {
           public static void main(String[] args) {
                     GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
                     ctx.load("app-context8.xml");
                     ctx.refresh();
                     MyBean bean1 = (MyBean)ctx.getBean("myBean1");
                     MyBean bean2 = (MyBean)ctx.getBean("myBean2");
                     System.out.println("---- bean1 ---");
                     bean1.run();
                     System.out.println("---- bean2 ---");
                     bean2.run();
                     ctx.close();
           }
}
[결과]
---- bean1 ---
사전 충고 받으시오::public void onj.edu.aop8.MyDependency.hello()
hello... OnJ
사전 충고 받으시오::public void onj.edu.aop8.MyDependency.goodbye()
goodbye... OnJ
---- bean2 ---
사전 충고 받으시오::public void onj.edu.aop8.MyDependency.hello()
hello... OnJ
goodbye... OnJ

댓글 없음:

댓글 쓰기