Аспект не выполнен весной - PullRequest
2 голосов
/ 16 февраля 2012

Я кодирую сайт, который будет почти полностью защищен логином (я использую Spring Security для него). Однако существуют определенные страницы, которые не защищены (домашняя страница, страница входа, страница регистрации, страница забытого пароля и т. Д.), И я пытаюсь достичь этого:

  • Если пользователь не вошел в систему при доступе к этим незащищенным страницам, покажи их нормально
  • Если пользователь уже вошел в систему, перенаправьте на домашняя страница (или страница, указанная в элементе аннотации redirectTo)

Конечно, я хочу избежать использования этого в каждом отдельном методе контроллера:

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

И по этой причине я хотел бы использовать АОП.

Я создал аннотацию @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();
}

Что-то не так в моем pointcut?

Спасибо.

Обновление: последний фрагмент этого вопроса вызывается, но все еще не вызывается для методов контроллера.

Ответы [ 3 ]

6 голосов
/ 16 февраля 2012

@ satoshi, я думаю, что проблема у вас в том, что вы используете Spring-AOP, и он может создавать прокси AOP только для bean-компонентов с интерфейсами - и в вашем случае контроллеры не имеют интерфейса.

Исправление может заключаться в использовании ткачества времени компиляции / загрузки с использованием AspectJ и не использовать Spring AOP OR, чтобы иметь jar-файлы cglib в classpath и принудительно создавать прокси на основе 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>
0 голосов
/ 27 ноября 2016

Что сработало для меня , пожалуйста, проверьте следующие пункты:

  • aspectjweaver.jar находится на пути к классам (версия 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>
0 голосов
/ 16 февраля 2012

Обычно, что бы я использовал перехватчик, а не аспект для этой цели. Например, создайте 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;
    }
  }
}

Надеюсь, это поможет.

...