java-即使在刷新上下文后,如何在Aspect中可靠地自动装配成员?

我有一个AspectJ方面,我想拥有@Autowired字段.鉴于默认情况下,方面是在Spring容器外部创建的单例,因此Spring不管理方面的任何依赖项注入.

在SO上搜索,Spring autowired bean for @Aspect aspect is null遇到了相同的问题,并且在方面使用@Configurable注释以某种方式神奇地允许Spring进行依赖项注入(see @codebrickie response).我仍不完全清楚该魔术的工作原理,但似乎效果很好.

现在,我的问题是,如果刷新Spring上下文,Spring不会更新依赖项以指向新bean.这是我的单元测试中的问题.我有一个定义了@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)的类,表示我想让Spring在每个测试方法之后刷新上下文.但是,考虑到它不会更新Aspect的依赖关系,我的第一个测试之后的任何测试都将失败,因为所引用的bean(第一次运行后会自动连接)不再有效.

样品测试班:

@DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD)
@Transactional
public class UserServiceImplTest extends TestBase {
    @Test
    @RequiredUserDetails(permissions={Permission.USER_LIST})
    public void testFindUser() throws Exception {
        User u = dod.getRandomUser();
        long userId = u.getId();

        User u2 = userService.findUser(userId);

        assertThat(u2, equalTo(u));
    }

    @Test(expected=AccessDeniedException.class)
    public void testFindUserWithoutPermissions() throws Exception {
        User u = dod.getRandomUser();
        long userId = u.getId();

        User u2 = userService.findUser(userId);

        assertThat(u2, equalTo(u));
    }
}

外观片段:

@Configurable
@Aspect
public class RequiredUserDetailsAspect {

    @Autowired UserRepository userRepository;

    @Pointcut("execution(public * *(..)) && @annotation(org.junit.Test)")
    public void testMethod() {};

    /**
     * Inject the specific permissions before test executes
     */
    @Before("testMethod() && requiresPermission(requiredUserDetails)")
    public void beforeTest( RequiredUserDetails requiredUserDetails){
        authenticateUser( userRepository.findOne( requiredUserDetails.id ) );
    }

    ...
    ...
    ...


}

如果我在beforeTest方法的方面中设置了断点,则可以看到在两个单元测试之间userRepository bean引用是相同的,即使从日志中可以看到Spring实例化了一个新的userRepository bean.因此,在第二次测试期间,该方面指向一个过时的bean.

如何指示Spring通过@Configurable实例刷新注入到方面中的依赖项?

解决方法:

我经常想知道为什么他们没有让Spring更轻松地管理方面.

但是要使这一方面在spring的管理下,您将以下内容放入了xml …不知道如何使用java配置.

尽管我认为配置也应该工作……尽管您可能会遇到生命周期冲突的问题.

<bean id="securityAspect" 
   class="com.afrozaar.ashes.core.security.AuthorizationAspect"> 
   factory-method="aspectOf" autowire="byType" />

方面编译器创建方面时,它将“ aspectOf”方法添加到类中.此方法可以访问作为方面的对象,并且在xml中具有此配置将在春季之前将该对象暴露给注入.

上一篇:没有-javaagent vm选项,Spring AspectJ编织如何工作?


下一篇:spring-aop-aspectj