【问题标题】:Autowired dependency not injected in Aspect in Spring MVC在 Spring MVC 的 Aspect 中未注入自动装配的依赖项
【发布时间】:2011-10-07 22:46:06
【问题描述】:

我无法@Autowire Aspect 中的服务层实例。在 Aspect 中,对 @Autowired bean 的引用为 NULL,它会抛出 NullPointerException。任何帮助都感激不尽。我想,我搞砸了配置。

以下是我的servlet-context.xml

<!-- Activates various annotations to be detected in bean classes -->
<context:annotation-config />
<context:spring-configured />       

<!-- Scans the classpath of this application for @Components to deploy as beans -->
<context:component-scan base-package="xx.yy" />

<!--  an @AspectJ aspect will be interpreted as an aspect by Spring AOP and beans in the context will be advised accordingly -->
<aop:aspectj-autoproxy />

<beans:bean id="loggingAspect" class="xx.yy.aop.aspects.LoggingAspect" />
<beans:bean id="authenticationAspect" class="xx.yy.aop.aspects.AuthenticationAspect" />

<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />

以下是我的观点:

@Configurable
@Component
@Aspect
public class AuthenticationAspect {
private static final Logger logger = LoggerFactory.getLogger(AuthenticationAspect.class);

@Autowired
private LoginService loginService;

    //.... 
}

这是我使用上面定义的@Authentication注解的控制器:

@Controller
@RequestMapping("/user")
public class UsersController {

@Autowired
private UserService userService;

@Authenticate
@RequestMapping(value="/{userId}/profile", method=RequestMethod.GET)    
public String displayUser(WebRequest webRequest, @PathVariable("userId") String userId, Model model) {
    User user = userService.findUser(Long.valueOf(userId));  
    model.addAttribute("user", user);
    model.addAttribute("AccordionMenuTab","5");
    model.addAttribute("selectedLink","profile");
    return "profile";
}

我收到以下异常:

Oct 8, 2011 3:12:48 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet appServlet threw exception
java.lang.NullPointerException
    at xx.yy.controller.UsersController.displayUser_aroundBody1$advice(UsersController.java:28)
    at xx.yy.controller.UsersController.displayUser(UsersController.java:1)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:662)

【问题讨论】:

    标签: spring-mvc aop aspectj spring-aop


    【解决方案1】:

    this piece of the documentation:

    7.8.3 使用 Spring IoC 配置 AspectJ 方面

    在 Spring 应用程序中使用 AspectJ 方面时,很自然地希望并期望能够使用 Spring 配置这些方面。 AspectJ 运行时本身负责创建切面,通过 Spring 配置 AspectJ 创建的切面的方式取决于切面使用的 AspectJ 实例化模型('per-xxx' 子句)。

    大多数 AspectJ 方面都是单例方面。这些方面的配置非常简单:只需像正常一样创建引用方面类型的 bean 定义,并包含 bean 属性“factory-method="aspectOf"”。这确保 Spring 通过向 AspectJ 请求它而不是尝试自己创建实例来获取切面实例。例如:

    <bean id="profiler" class="com.xyz.profiler.Profiler"
          factory-method="aspectOf" />
    

    【讨论】:

    • 文档体积庞大,但为王。
    • 添加 factory-method="aspectOf" 解决了我的问题,谢谢!!
    • 你好,你知道如何翻译成java配置吗?
    【解决方案2】:

    对于任何寻找基于 java 的 bean 配置的人,使用 java 反射我可以将其归档

    @Bean
    public ExceptionAspectHandler exceptionAspectHandler(){
        try
        {
            //noinspection JavaReflectionMemberAccess
            Method method = ExceptionAspectHandler.class.getMethod("aspectOf" );
            return (ExceptionAspectHandler) method.invoke(null);
        }
        catch( IllegalAccessException | InvocationTargetException | NoSuchMethodException e )
        {
           logger.log( Level.SEVERE, "Error creating bean : ", e );
        }
        return null;
    }
    

    由于aspectOf() 方法在编译期间不可用,我们不能仅通过调用该方法来创建bean。这就是 XML 配置能够处理它的原因。

    另一种更简单的方法

    @Bean
    public ExceptionAspectHandler exceptionAspectHandler()
    {
        return Aspects.aspectOf( ExceptionAspectHandler.class );
    }
    

    这也有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-21
      • 1970-01-01
      • 2012-10-27
      • 1970-01-01
      • 1970-01-01
      • 2016-09-17
      • 1970-01-01
      相关资源
      最近更新 更多