> Hello World !!!

     

@syaku

스프링 AOP bean 주입시 트랜잭션 무시되는 문제 : Spring AOP Transaction ignore

스프링 AOP bean 주입시 트랜잭션 무시되는 문제 : Spring AOP Transaction ignore

서비스(빈)를 AOP에 주입하면 트랜잭션이 무시되는 문제가 있다. 어떻게 작업을 했는 지 아래의 소스를 보도록한다.

@Service
@Transactional
public class DemoService {
    @Resource(name = "demoDAO") private DemoDAO demoDAO;

    @Transactional(readOnly = true)
    public List<Demo> getDemoList() {
        return (List<Demo>) demoDAO.findAll();
    }

    public Demo saveDemo(Demo demo) {
        return demoDAO.save(demo);
    }

    public void saveTest(Demo demo) {
        saveTest(demo, false);
    }
    public void saveTest(Demo demo, boolean is) {
        saveDemo(demo);
        throw new RuntimeException(""); // 롤백을 위한 강제 익셉션
    }

    public void getTest() {
        System.out.println("aop 요청.");
    }
}

서비스 클래스를 만들었다.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = BootstrapContext.class)
@ActiveProfiles({"dev", "jpa"})
public class TestDemo {
    @Resource(name = "demoService") private DemoService demoService;

    @Test
    public void crud() {
        Demo demo = new Demo("syaku", "제목", "내용");
        demoService.saveTest(demo, false);
        System.out.println(demoService.getDemoList().size());
    }
}

테스트 클래스를 만들다. 위 소스는 실행하면 문제없이 롤백이 된다. 하지만 아래와 같이 DemoService 를 xml 스키마 기반으로 AOP를 설정하면 트랜잭션이 무시가 된다. 아래의 설정이 사용되며 선언적인 트랜잭션 설정이 무시되는 것 같다.

<?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.xsd
    ">

    <aop:config>

        <aop:aspect id="demoServiceAOP" ref="demoService">
            <aop:pointcut id="demoServiceAOPPointcut" expression="execution(* org.springframework.security.web.authentication.logout.LogoutHandler.*(..))" />
            <aop:after pointcut-ref="demoServiceAOPPointcut" method="getTest" />
        </aop:aspect>

    </aop:config>

</beans>

단 Java기반 AOP 설정은 무시되지 않는 것 같다. 즉 아래와 같이 하면 문제가 되지 않는 다.

@Aspect
@Component
public class DemoServiceAOP {
    @Resource(name = "demoService") DemoService demoService;
    
    @Pointcut("execution(execution(* org.springframework.security.web.authentication.logout.LogoutHandler.*(..))")
    private void demoServiceAOPPointcut() {}

    @After("demoServiceAOPPointcut()")
    public void getTest(JoinPoint thisJoinPoint) {
        demoService.getTest();
    }
}

xml 스키마 기반으로 AOP를 사용하려면 주입할때 demoService를 AOP용으로 새로만들어 사용하면 문제를 해결할 수 있다.

@Component
public class DemoAOPSupport {
    @Resource(name = "demoService")
    DemoService demoService;

    public void getTest() {
        demoService.getTest();
    }
}

<aop:aspect id="demoServiceAOP" ref="demoAOPSupport"> 이렇게 주입해주면 된다.

로그를 확인하기 위한 설정

<logger name="org.springframework.jdbc" level="debug" />
<logger name="org.springframework.aop" level="debug" />



posted syaku blog

Syaku Blog by Seok Kyun. Choi. 최석균.

http://syaku.tistory.com