Aspect没有在Spring中执行

时间:2012-02-16 12:01:00

标签: spring spring-mvc spring-aop

我正在编写一个几乎完全受登录保护的网站(我正在使用Spring Security)。但是有些页面没有受到保护(主页,登录页面,注册页面,忘记密码页面......)以及我想要实现的目标是:

  • 如果用户在访问这些非安全页面时未登录, 通常显示它们
  • 如果用户已登录,请重定向到 主页(或redirectTo注释元素中指定的页面)

当然我想避免将它放在每个控制器方法中:

if(loggedIn())
{
    // Redirect
}
else
{
    // Return the view
}

因此我想使用AOP。

我创建了注释@NonSecured,我编写了以下方面:

@Aspect
public class LoggedInRedirectAspect
{
    @Autowired
    private UserService userService;

    @Around("execution(@my.package.annotation.NonSecured * *(..))")
    public void redirect(ProceedingJoinPoint point) throws Throwable
    {
        System.out.println("Test");
        point.proceed();
    }
}

示例注释方法:

@Controller
@RequestMapping("/")
public class HomeController
{
    @NonSecured(redirectTo = "my-profile")
    @RequestMapping(method = RequestMethod.GET)
    public String index(Model model,
                        HttpServletRequest request) throws Exception
    {
        // Show home page
    }
}

applicationContext.xml重要位:

<context:annotation-config />
<context:component-scan base-package="my.package" />

<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />

<bean id="loggedInRedirectAspect" class="my.package.aspect.LoggedInRedirectAspect" />
<aop:aspectj-autoproxy proxy-target-class="true">
    <aop:include name="loggedInRedirectAspect" />
</aop:aspectj-autoproxy>

问题是方面中的方法redirect(...)永远不会被调用。 一般来说方面工作正常,实际上会调用方面中的以下方法:调用以下建议,但不会调用控制器方法。

@Around("execution(* *(..))")
public void redirect(ProceedingJoinPoint point) throws Throwable
{
    point.proceed();
}

我的切入点是否有问题?

谢谢。

更新:此问题中的最后一个片段被调用,但仍未调用控制器方法。

3 个答案:

答案 0 :(得分:6)

@satoshi,我认为您遇到的问题是因为您使用的是Spring-AOP,它只能为具有接口的bean创建AOP代理 - 在您的情况下,控制器没有接口。

修复可能是使用AspectJ使用编译时/加载时编织,并且不使用Spring AOP OR在类路径中使用cglib jar并强制基于cglib的代理创建:

<aop:aspectj-autoproxy proxy-target-class="true"/>

更新: 编译时编织可以使用maven插件完成,showWeaveInfo配置将准确显示已编织的类:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <version>1.0</version>
    <dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.6.10</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjtools</artifactId>
            <version>1.6.10</version>
        </dependency>
    </dependencies>
    <executions>
        <execution>
            <goals>
                <goal>compile</goal>
                <goal>test-compile</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <outxml>true</outxml>
        <verbose>true</verbose>
        <showWeaveInfo>true</showWeaveInfo>
        <aspectLibraries>
            <aspectLibrary>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
            </aspectLibrary>
        </aspectLibraries>
        <source>1.6</source>
        <target>1.6</target>
    </configuration>
</plugin>

答案 1 :(得分:0)

通常我会使用拦截器而不是用于此目的的方面。例如,创建一个RequestInitializeInterceptor,它将检查安全主体并相应地重定向。对于这项工作来说,方面是一种矫枉过正。对于特定控制器的每个请求,拦截器将充当前端控制器,并决定是否允许传输请求。

 public class RequestInitializeInterceptor extends HandlerInterceptorAdapter {

  // Obtain a suitable logger.
  private static Log logger = LogFactory
      .getLog(RequestInitializeInterceptor.class);

  /**
   * In this case intercept the request BEFORE it reaches the controller
   */
  @Override
  public boolean preHandle(HttpServletRequest request,
      HttpServletResponse response, Object handler) throws Exception {
    try {

      logger.info("Intercepting: " + request.getRequestURI());

      // Your logic to redirect accordingly
     if (userAuthenticated) {
       response.sendRedirect(URL);
       return false;
    }
      return true;
    } catch (SystemException e) {
      logger.info("request update failed");
      return false;
    }
  }
}

希望这有帮助。

答案 2 :(得分:0)

有用的内容,请检查以下几点:

  • aspectjweaver.jar在classpath(版本1.6.8或更高版本)
  • Aspect类使用@Aspect@Component
  • 进行注释
  • 您启用了spring aspectJ-auto-proxy

Java配置:

@Configuration
@ComponentScan("io.mc.springaspects")
@EnableAspectJAutoProxy
public class SpringConfiguration {
}

方面:

@Aspect
@Component
public class AnnotationAspect {
   ...
}

的Maven:

<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.8.9</version>
</dependency>