스프링 Proxy AOP 사용 관련 문제. 문제..원인이라도 알고 싶어서 올립니다.

665 views
Skip to first unread message

진교 김

unread,
Feb 27, 2013, 3:13:26 AM2/27/13
to ks...@googlegroups.com
한참을... 헤매고.. 찾아봐도 문제가 어디부터 시작되는지 몰라서 여쭤봅니다.

환경은 struts2(2.3.1.2), spring(3.1.1.RELEASE), java 1.5, weblogic 10.0 이며

1)root applicationContext로
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/classes/config/applicationContext.xml
            /WEB-INF/classes/config/applicationContext-jdbc.xml
            /WEB-INF/classes/config/spr_appCntx_common.xml
        </param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

2)servlet context 는
    <servlet>
        <servlet-name>springapp</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
            /WEB-INF/classes/config/total-applicationContext.xml
            </param-value>
        </init-param>
    </servlet>


<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"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context-3.1.xsd
                        http://www.springframework.org/schema/aop
                        http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
                        http://www.springframework.org/schema/tx
                        http://www.springframework.org/schema/tx/spring-tx-3.1.xsd" >

    <context:component-scan base-package="com.my.package" />
    <aop:aspectj-autoproxy />
   
    ...(생략)
</beans>

와 같이 설정된 상황입니다.

기존에 사용중인 transactionProxy 가 존재하는데. root applicationContext 상에 아래와 같이 있습니다.
    <bean id="CommAroundAdvice" class="com.my.finehr.common.CommonAroundAdvice"/>

    <!-- Common Advisor pointcut definition for around advice -->
    <bean id="CommAroundAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <property name="advice">
            <ref bean="CommAroundAdvice"/>
        </property>
        <property name="pattern">
            <value>.*</value>
        </property>
    </bean>

    <bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
          abstract="true">
        <property name="transactionManager"><ref bean="transactionManager"/></property>
        <property name="transactionAttributes">
            <props>
                <prop key="retrieve*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="select*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="list*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="search*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="aut_chk">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="*">PROPAGATION_REQUIRED,-NullPointerException,-DataAccessException,-BizException,+AuthException</prop>
            </props>
        </property>
        <property name="preInterceptors">
            <list>
                <ref bean="CommAroundAdvisor"/>
            </list>
        </property>
    </bean>

=================================
여기서...질문 입니다.
servlet context 에 aop 태그를 사용한 proxy 적용을 하고 싶은데.
<aop:aspectj-autoproxy /> 태그 적용 시  @Aspect annotation을 사용한 클래스를 찾는게 아닌.
root applicationContext 상의 CommAroundAdvisor 를.. 찾게 되네요.

클래스 코드는 아래와 같으며.
package com.my.total.common.aop;

import ...(생략)

@Aspect
@Component
public class SessionAspect {
    @Pointcut("execution(* *(..))")
    private void all() {}
    @Around("all()")
    public Object logJoinPoint(ProceedingJoinPoint pointCut) throws Throwable {
        System.out.println("AOP 1 단계 ===========================================");
        Object ret = null;
        try {
            ret = pointCut.proceed();
        } catch (AuthException ex) {
            System.out.println("야야야야야야 CommonAdvice 싫어!!!!");
        }
        System.out.println("===========================================AOP 1 단계 끝");
        return ret;
    }
}

위 와 같은 상황에서 실행 시 오류내용은 아래와 같습니다.
<2013. 2. 27 오후 5시 11분 09초 KST> <Error> <HTTP> <BEA-101017> <[weblogic.servlet.internal.WebAppServletContext@169be56 - appName: 'fineHR', name: 'null', context-path: ''] Root cause of ServletException.
java.lang.reflect.UndeclaredThrowableException
        at $Proxy368.toString(Unknown Source)
        at java.lang.String.valueOf(String.java:2615)
        at java.lang.StringBuilder.append(StringBuilder.java:116)
        at org.springframework.web.servlet.DispatcherServlet.initLocaleResolver(DispatcherServlet.java:488)
        at org.springframework.web.servlet.DispatcherServlet.initStrategies(DispatcherServlet.java:439)
        Truncated. see log file for complete stacktrace
com.my.finehr.common.AuthException: 로그인 되어 있지 않습니다.
        at com.my.finehr.common.CommonAroundAdvice.invoke(CommonAroundAdvice.java:48)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
        Truncated. see log file for complete stacktrace
>

ㅠ.ㅠ.. 문제 원인부터 파악 할수 있었으면 좋겠네요..

진교 김

unread,
Feb 27, 2013, 3:15:48 AM2/27/13
to ks...@googlegroups.com
<aop:aspectj-autoproxy /> 코드 삭제 시 정상 수행은 하게 됩니다.

... 스프링이 aop 태그가 사용으로 advisor를 자동 선택 하게 하는거 같은데....
어떻게 선택하는지....알기가 참... 어렵네요

skplanet

unread,
Feb 27, 2013, 3:20:47 AM2/27/13
to ks...@googlegroups.com
CommonAroundAdvice 이부분 내용을 보고 싶네요 

--
Google 그룹스 'Korea Spring User Group' 그룹에 가입했으므로 본 메일이 전송되었습니다.
이 그룹에서 탈퇴하고 더 이상 이메일을 받지 않으려면 ksug+uns...@googlegroups.com에 이메일을 보내세요.
이 그룹에 게시하려면 ks...@googlegroups.com(으)로 이메일을 보내세요.
http://groups.google.com/group/ksug?hl=ko에서 그룹을 방문하세요.
더 많은 옵션을 보려면 https://groups.google.com/groups/opt_out을(를) 방문하세요.
 
 

진교 김

unread,
Feb 27, 2013, 3:31:47 AM2/27/13
to ks...@googlegroups.com
package com.my.finehr.common;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;

public class CommonSessionAroundAdvice implements MethodInterceptor {

    protected final Logger logger = Logger.getLogger(this.getClass());

    public Object invoke(MethodInvocation invocation) throws Throwable {

        String className = invocation.getThis().getClass().getName();
        if (logger.isDebugEnabled()) {
            logger.debug(className + "." + invocation.getMethod().getName() + "()" + " 시작!!!");
            Object[] args = invocation.getArguments();
            if ((args != null) && (args.length > 0)) {
                for (int i = 0; i < args.length; i++) {
                    logger.debug("Argument[" + i + "] : " + args[i]);
                }
            }
        }

        HttpServletRequest request = ServletActionContext.getRequest();
        HttpSession session = request.getSession();
        // authentication
        if (session == null || session.getAttribute("emp_no") == null)
            throw new AuthException("로그인 되어 있지 않습니다.");

        // target class 의 method 를 실행시킨다.
        Object rtnObj = invocation.proceed();

        if (logger.isDebugEnabled()) {
            logger.debug(className + "." + invocation.getMethod().getName() + "()" + " 종료!!!");
        }

        return rtnObj;
    }
}

완전 동일한 코드는 아니지만. 위 코드와 같이 되어 있습니다.(세부적인 내용이 들어가서. 코드가 긴걸 줄였습니다.)

Ki-Seok Kim

unread,
Feb 27, 2013, 3:46:44 AM2/27/13
to ks...@googlegroups.com
저도 잘은 모르지만 pointcut execution 을 저런식으로 쓰면 모든 메소드에 적용되는거 아닌가요?

메일쓰실때 package 명 숨길려고 지우신건가요?



2013/2/27 진교 김 <kjkj...@gmail.com>

진교 김

unread,
Feb 27, 2013, 4:01:14 AM2/27/13
to ks...@googlegroups.com
기존에 개발되었던.(제가 개발한게 아니라서...)
CommAroundAdvice 의 경우. 메소드 패턴에 따른 proxy 적용이 아닌. 클래스 단위로 적용이 되다보니.
=======
    <bean id="com.my.finehr.xhr.kita.KitaDaoTarget" class="com.my.finehr.xhr.kita.KitaDaoImpl">
        <property name="sqlMapClient"><ref bean="sqlMapClient"/></property>
    </bean>
    <!-- 기타시스템  Dao-->
    <bean id="com.my.finehr.xhr.kita.KitaDao" parent="baseTransactionProxy">
        <property name="target"><ref bean="com.my.finehr.xhr.kita.KitaDaoTarget"/></property>
    </bean>
=======
기존 부분을 수정하기는 좀 어려울것 같고.


제가 현재 테스트 하고 있는 SessionAspect 의 경우 @Pointcut("execution(* *(..))") 은 수정 할 예정입니다.
패키지명 숨기려고 한 의도는 아니고.. SessionAspect 가 실행되지 않다보니. 위와 같이 해서.. 실행이 되는지 확인 하려고 해둔 상황이에요




2013년 2월 27일 수요일 오후 5시 46분 44초 UTC+9, Ki-Seok Kim 님의 말:
Reply all
Reply to author
Forward
0 new messages