Spring @Aspect没有正确自动装配

时间:2016-07-01 11:24:32

标签: java spring dependency-injection aspectj

我有以下代码:

package com.cooldomain.coolapp.application.rest.session;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class SessionAspect
{
    @Autowired
    private HttpServletRequest request;

    @Autowired
    private SessionService sessionService;

    @PostConstruct
    public void init()
    {
        /*
        * XXX Note: On application startup this piece of code prints the right values and I can see that they have been autowired correctly:
        * ------------------------------------------------------------------------------------------------
        * request: Current HttpServletRequest
        * sessionService: com.cooldomain.coolapp.application.rest.session.SessionService@3700511f
        * ------------------------------------------------------------------------------------------------
        */
        System.out.println("request: " + request);
        System.out.println("sessionService: " + sessionService);
    }

    @Around("@annotation(com.cooldomain.coolapp.application.rest.session.SessionRequired) && within(com.cooldomain.coolapp.application..*)")
    public Object proceedWithValidSession(ProceedingJoinPoint joinPoint) throws Throwable
    {
        /*
        * XXX Note: But when I make a request to the annotated with @SessionRequired method i get the following output and hence a nullpointer exception afterwards:
        * ------------------------------------------------------------------------------------------------
        * request: null
        * sessionService: null
        * ------------------------------------------------------------------------------------------------
        */
        System.out.println("request: " + request);
        System.out.println("sessionService: " + sessionService);

        return setSessionAsFirstArgument(joinPoint);
    }

    private Object setSessionAsFirstArgument(ProceedingJoinPoint joinPoint) throws Throwable
    {
        Object[] args = joinPoint.getArgs();
        args[0] = sessionService.getSession(request);

        return joinPoint.proceed(args);
    }
}

所以问题在于,当我启动应用程序时,所有内容都会正确地自动装配,但是当我向带注释的方法发出请求时,自动装配的字段会神奇地设置为null。我不确定spring是否使用这个bean或者试图创建另一个bean ...

注意:这段代码存在于另外两个项目中,并且它的绝对值相同(复制/粘贴)并且它完美地运行,但是它在这里打破...我使用的是Spring版本4.1.5和aspectjrt 1.8.5就像在其他两个项目中一样。

我已经完成了以下解决方法,其工作原理,但它很难看,我想删除它:

package com.cooldomain.coolapp.application.rest.session;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class SessionAspect
{
    @Autowired
    private HttpServletRequest request;

    @Autowired
    private SessionService sessionService;

    // WORKAROUND
    private static SessionAspect sessionAspect;

    @PostConstruct
    public void init()
    {
        /*
         * Note: On application startup this piece of code prints the right values and I can see that they have been autowired correctly:
         * ------------------------------------------------------------------------------------------------
         * request: Current HttpServletRequest
         * sessionService: com.cooldomain.coolapp.application.rest.session.SessionService@3700511f
         * ------------------------------------------------------------------------------------------------
         */
        System.out.println("request: " + request);
        System.out.println("sessionService: " + sessionService);

        // WORKAROUND
        sessionAspect = this;
    }

    @Around("@annotation(com.cooldomain.coolapp.application.rest.session.SessionRequired) && within(com.cooldomain.coolapp.application..*)")
    public Object proceedWithValidSession(ProceedingJoinPoint joinPoint) throws Throwable
    {
        /*
         * XXX Note: But when I make a request to the annotated with @SessionRequired method i get the following output and hence a nullpointer exception afterwards:
         * ------------------------------------------------------------------------------------------------
         * request: null
         * sessionService: null
         * ------------------------------------------------------------------------------------------------
         */
        System.out.println("request: " + request);
        System.out.println("sessionService: " + sessionService);

        // WORKAROUND
        return sessionAspect.setSessionAsFirstArgument(joinPoint);
    }

    private Object setSessionAsFirstArgument(ProceedingJoinPoint joinPoint) throws Throwable
    {
        Object[] args = joinPoint.getArgs();
        args[0] = sessionService.getSession(request);

        return joinPoint.proceed(args);
    }
}

有人知道如何解决这个问题吗?

2 个答案:

答案 0 :(得分:0)

.OK所以事实证明,Spring不应该受到责备而只会创建一个bean。 我看到了项目xml和插件 aspectj-maven-plugin(aspectj-maven-plugin),它在spring上下文之外创建了另一个类实例,而@Aspect使用了这个实例 - 而不是春天一个 如果只能制作spring bean而不删除插件,那么会在网上查找soltion ...也许在配置中有一个排除选项

答案 1 :(得分:0)

我不知道你为什么不使用joinPoint.proceed();在你周围的建议。 必须提出建议才能开展工作。

@Around("@annotation(com.cooldomain.coolapp.application.rest.session.SessionRequired) && within(com.cooldomain.coolapp.application..*)")
    public Object proceedWithValidSession(ProceedingJoinPoint joinPoint) throws Throwable
    {
//your code

//solution
joinPoint.proceed(); 
    }

请试一试,并说明发生了什么。