注入的实例变量在方面执行时为空

发布于 2024-11-15 08:34:43 字数 1311 浏览 2 评论 0原文

我在 Spring AOP 中遇到了这个奇怪的问题,我希望有人能对此有所了解。

我正在使用 CGLIB 代理,当我执行以下方面时,我得到一个空指针:

@Aspect
@Component //i.e. Singleton
public class MyAspect {

    private static final Logger logger = LoggerFactory.getLogger(MyAspect.class);

    {

        logger.debug("new instance of MyAspect");  //Line 1
    }

    private AutowireCapableBeanFactory factory;

    @Inject
    public MyAspect(AutowireCapableBeanFactory factory) {

        if (factory ==null) {

            logger.debug("your factory is null");  //Line 2
        } else {

            logger.debug("your factory is not null");
        }
        this.factory = factory;
    }

    @AfterReturning(pointcut = "@annotation(com.domain.annotations.MyAnnotation)")
    public void doSomething() {

        if (factory ==null) {

            logger.debug("your factory is null again");  //Line 3
        }

                    // this is a request scoped bean
        MyRequest request = factory.getBean(MyRequest.class);  //Line 4



        if (request != null) {
            logger.debug("No");
            }
        else {
            logger.debug("Yes");
            }
    }
}

我在第 4 行收到 NullPointerException。我可以看到第 3 行的“工厂”为空,但在创建实例时它不为空在第 2 行。我还跟踪在第 1 行创建的实例。

此设计使用接口(JDK 动态代理)进行工作。为什么我的实例变量在运行时变为空,有解决方法吗?

I have this odd problem with Spring AOP and I am hoping someone can shed some light on it.

I am using CGLIB proxies and when I execute the following aspect i get a null pointer:

@Aspect
@Component //i.e. Singleton
public class MyAspect {

    private static final Logger logger = LoggerFactory.getLogger(MyAspect.class);

    {

        logger.debug("new instance of MyAspect");  //Line 1
    }

    private AutowireCapableBeanFactory factory;

    @Inject
    public MyAspect(AutowireCapableBeanFactory factory) {

        if (factory ==null) {

            logger.debug("your factory is null");  //Line 2
        } else {

            logger.debug("your factory is not null");
        }
        this.factory = factory;
    }

    @AfterReturning(pointcut = "@annotation(com.domain.annotations.MyAnnotation)")
    public void doSomething() {

        if (factory ==null) {

            logger.debug("your factory is null again");  //Line 3
        }

                    // this is a request scoped bean
        MyRequest request = factory.getBean(MyRequest.class);  //Line 4



        if (request != null) {
            logger.debug("No");
            }
        else {
            logger.debug("Yes");
            }
    }
}

I am getting a NullPointerException at Line 4. I can see that the "factory" is null at Line 3 but it is not null when the instance is create at Line 2. I am also tracking the instances being created at Line 1.

This design works using interfaces (JDK dynamic proxies). Why do my instances variables become null at runtime and is there a work around to this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦旅人picnic 2024-11-22 08:34:43

总而言之,您不能将 Spring 的基于构造函数的注入与 Aspect 结合使用。 此处有关于此主题的很好的论坛讨论。

我个人按照上述论坛中的建议,对我的方面使用基于属性的注入。下面的示例允许您将服务注入审计方面。您不需要任何额外的 XML 配置,只要您的方面实现 ApplicationContextAware 即可。

@Aspect
@Component("auditAspect")
public class AuditAspect implements ApplicationContextAware {

ApplicationContext context;

public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
    // do stuff with context here
}

public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;       
 }

Long and short is that you can't use Spring's constructer based injection with Aspects. There's a good forum discussion on this topic here.

I personally use property-based injection for my aspects as suggested in the above forum. The example below allows you to inject a service into an auditing aspect. You don't need any additional XML configuration, as long as you make your aspect implement ApplicationContextAware.

@Aspect
@Component("auditAspect")
public class AuditAspect implements ApplicationContextAware {

ApplicationContext context;

public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
    // do stuff with context here
}

public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;       
 }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文