11

「アスペクト」に @Autowired アノテーションを使用したい。自分のアスペクトにリポジトリを挿入したいのですが、自動配線されたクラスのメソッドを呼び出そうとすると、NullPointException が発生します。

@Aspect
public class AspectSecurity {

@Autowired
private UserRepository userRepository;


@After("execution(public * dash.*.*Controller.*(..))")
public void authentication(JoinPoint jp) throws UnauthorizedException {
    System.out.println("SECURITY !");

    System.out.println(userRepository.findAll().toString());

   }
}

@Componentアスペクトクラスの上に追加しようとしましたが、同じエラーが発生しました。

アスペクト クラスを使用せ@Controllerずにリポジトリを問題なく呼び出すことができます。

一部のドキュメントでは、xml ファイルを使用したスプリング構成について説明していますが、スプリング ブートではこれらのファイルがありません。

ここに、aspectJ プラグインを呼び出す pom.xml の一部があります。

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <version>1.4</version>
    <configuration>
        <showWeaveInfo>true</showWeaveInfo>
        <source>1.6</source>
        <target>1.6</target>
        <Xlint>ignore</Xlint>
        <complianceLevel>${compiler.version}</complianceLevel>
        <encoding>UTF-8</encoding>
        <verbose>false</verbose>
        <aspectLibraries>
            <aspectLibrary>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
            </aspectLibrary>
        </aspectLibraries>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>compile</goal>
                <goal>test-compile</goal>
            </goals>
        </execution>
    </executions>
    <dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${aspectj.version}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjtools</artifactId>
            <version>${aspectj.version}</version>
        </dependency>
    </dependencies>
</plugin>

ここで私のアプリケーションクラス:

package dash;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan;

@ComponentScan
@EnableAutoConfiguration
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

ここでは、アスペクトが呼び出される Controller クラス:

package dash.user;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import dash.GenericController;

@Controller
@RequestMapping("/user")
public class UserController extends GenericController {

@Autowired
private UserRepository repository;

@RequestMapping("/findAll")
public @ResponseBody User create(
        @RequestParam(value="login", required=true) String login,
        @RequestParam(value="password", required=true) String password) {
    
    System.out.println(login);
    System.out.println(password);
    

    System.out.println("Users found with findAll():");
    System.out.println("-------------------------------");
    for (User user : repository.findAll()) {
        System.out.println(user);
    }
    
    
    return  repository.findOne("root");
    }
}

注:私はすでに@EnableAspectJAutoProxyアプリケーションクラスの上に追加しようとしました。

4

2 に答える 2

19

AspectJ ウィービングのセットアップは非常に難しいため、ここでいくつか問題が発生する可能性があります。で使用しないことをお勧めし@Componentます@Aspect(または、少なくとも から除外されていることを確認してください@ComponentScan)。その理由は@Bean、そのタイプの を作成し、AspectJ と同じ作成メカニズムを明示的に使用して、Spring と AspectJ がシングルトン インスタンスの値に同意する必要があるためです。それを行う正しい方法はAspects@Bean定義で静的な便利なメソッドを使用することだと思います。例えば

@Bean
public AspectSecurity interceptor() {
    AspectSecurity aspect = Aspects.aspectOf(AspectSecurity.class);
    // ... inject dependencies here if not using @Autowired
    return aspect;
}

aop.xmlさらに、コンパイルされたアスペクトが AspectJ ウィーバー パス上にあることを確認する必要があります。それが Maven AspectJ プラグインで行っていることかもしれませんが、私がこれを行っている場合は、おそらくaop.xml手動で作成し、 を使用@EnableLoadTimeWeavingして、プラグインを捨てるでしょう。何が機能するかに基づいて、おそらく自分で決めることができます。

アスペクトがアプリケーション コンテキストの構築中に使用されるものをインターセプトする必要がある場合、ライフサイクルの問題が発生する可能性もあります。メソッドのインターセプトに依存しないことでそれを回避できるかもしれません。そうしないと、特定の順序で Bean を作成しようとして@Beanゲームをプレイすることになります。@DependsOnあなたのアプリがそれに苦しんでいるかどうかはまだわかりません。

以前 (Spring Boot 1.3 で廃止):

もう 1 つの障害は、Spring Boot を使用して@EnableAutoConfigurationいて、明示的に on@EnableAspectJAutoProxyに切り替えていることと、Spring Bean アスペクトの AspectJ ウィービングをオフに切り替えていることです。それが意図した副作用であるかどうかは実際にはわかりません@EnableAspectJAutoProxyが、autoconfigから除外することで無効にすることができます。

@ComponentScan
@EnableAutoConfiguration(exclude=AopAutoConfiguration.class)
public class Application {    
    ...
}

注意: この構成を除外するのを忘れると、ウィービングがオフになっていることに気付かないかもしれません。これは、Spring がプロキシを作成し、アスペクトの多くがとにかく機能するためです。

于 2014-01-26T19:16:30.593 に答える