如何在Aspect中可靠地自动装配成员 - 即使在上下文刷新之后? [英] How to Autowire members reliably inside an Aspect - even after a context refresh?

查看:217
本文介绍了如何在Aspect中可靠地自动装配成员 - 即使在上下文刷新之后?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an AspectJ aspect in which I want to have @Autowired fields. Given that by default, the aspects are singletons created outside the Spring container, Spring does not manage any of the dependency injection for the aspect.

搜索SO, @Aspect方面的Spring自动装配bean为空遇到同样的问题,并使用 @Configurable 方面的注释以某种方式神奇地允许Spring进行依赖注入(参见@codebrickie响应)。我还不完全清楚这个魔法是如何工作的,但似乎工作正常。

Searching around on SO, Spring autowired bean for @Aspect aspect is null encountered the same problem, and using the @Configurable annotation on the aspect somehow magically allows Spring to do the dependency injection (see @codebrickie response). I'm still not entirely clear how that magic works, but it seems to work fine.

我的问题,现在,如果我刷新Spring上下文,Spring会不更新依赖项以指向新bean。这是我单元测试中的一个问题。我有一个定义了 @DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)的类,表示我希望spring在每个测试方法之后刷新上下文。但是,鉴于它没有更新Aspect的依赖关系,我第一次测试后的任何测试都会失败,因为引用的bean(从第一次运行开始自动装配)不再有效。

My problem, now, is that if I refresh the Spring context, Spring does not update the dependencies to point to the new beans. This is a problem in my unit tests. I have a class with @DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD) defined, indicating that I want spring to refresh the context after each test method. However, given that it doesn't update the Aspect's dependencies, any tests after my first test fail given that the referenced beans (left over autowired from the first run) are no longer valid.

示例测试类:

@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));
    }
}

Aspect片段:

@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引用在2个单元测试之间是相同的,即使从日志中我可以看到Spring已经实例化了一个新的userRepository bean。因此,在第二次测试期间,方面指向一个陈旧的bean。

If I put a breakpoint in my aspect in the beforeTest method, I can see that the userRepository bean reference is the same between the 2 unit tests, even though from the logs I can see that Spring has instantiated a new userRepository bean. Consequently, during the second test, the aspect is pointing to a stale bean.

如何指示Spring通过<$刷新它注入到方面的依赖项c $ c> @Configurable 实例化?

How can I instruct Spring to refresh the dependencies that it injected into the aspect via the @Configurable instantiation?

推荐答案

我经常想知道他们为什么不去让spring更容易管理方面。

I've have often wondered why they don't make it easier for spring to manage the aspect.

但为了使方面弹簧管理你将以下内容放入你的xml ......不知道你是怎么做的d使用java配置。

But to make the aspect spring managed you put the following into your xml... Don't know how you'd do it with java configuration.

虽然我认为配置也应该有效...尽管你可能遇到生命周期冲突的问题。

Though I think configuration should work as well... although you may have issues with life cycle conflicts.

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

当方面编译器创建方面时,它会将aspectOf方法添加到类中。此方法允许访问作为方面的对象,并且在xml中具有此配置将通过spring将该对象暴露给注入等。

When the aspect compiler creates an aspect it adds that "aspectOf" method to the class. This method gives access to the object that is the aspect and having this config in your xml will expose that object to injection etc by spring.

这篇关于如何在Aspect中可靠地自动装配成员 - 即使在上下文刷新之后?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆