5

管理されていない JPA ドメイン クラスがあります。new演算子を介してインスタンス化されます。

UserAccount account = new UserAccount();
userRepository.save(account)

私のUserAccountクラスには、パスワードをハッシュエンコードするためのbeforeSave()my に依存するメソッドがあります。SecurityService

私の質問は、「Spring DI を取得してセキュリティ サービスをエンティティに挿入するにはどうすればよいですか?」です。AspectJ と LoadTimeWeaving が必要なようです。構成用の配列を試しましたが、どれも機能しないようです。NullPointerException注入されたオブジェクトでメソッドを呼び出そうとすると、常にエラーが発生します。

UserAccount.java (これは JPA エンティティです)

@Entity
@Repository
@Configurable(autowire = Autowire.BY_TYPE)
public class UserAccount implements Serializable {

    @Transient
    @Autowired
    SecurityService securityService;

    private String passwordHash;

    @Transient
    private String password;

    public UserAccount() {
        super();
    }

    @PrePersist
    public void beforeSave() {
        if (password != null) {
            // NullPointerException Here!!!
            passwordHash = securityService.hashPassword(password);  
        }
    }
}

AspectJ を使用するように春に指示しようとしています:

NitroApp.java (メインクラス)

@SpringBootApplication
@EnableTransactionManagement
@EnableSpringConfigured
@PropertySources(value = {@PropertySource("classpath:application.properties")})
public class NitroApp extends SpringBootServletInitializer {


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

}

build.gradle (構成)

buildscript {
    repositories {
        mavenCentral()
        jcenter()
    }

    dependencies {
        classpath "org.springframework.boot:spring-boot-gradle-plugin:1.2.2.RELEASE"
        classpath "org.springframework:springloaded:1.2.2.RELEASE"
        classpath "org.springframework:spring-aspects:4.1.6.RELEASE"
    }
}

apply plugin: 'java'
apply plugin: 'aspectj'
apply plugin: 'application'
apply plugin: 'idea'
apply plugin: 'spring-boot'

repositories {
    jcenter()
    mavenLocal()
    mavenCentral()
}

mainClassName = 'com.noxgroup.nitro.NitroApp'
applicationName = "Nitro"

idea {
    module {
        inheritOutputDirs = false
        outputDir = file("$buildDir/classes/main/")
    }
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")
    compile("org.springframework.boot:spring-boot-starter-thymeleaf")
    compile("org.springframework.boot:spring-boot-starter-actuator")
    compile("org.springframework.boot:spring-boot-starter-data-jpa")
    compile("net.sourceforge.nekohtml:nekohtml:1.9.15")
    compile("commons-codec:commons-codec:1.9")
    compile("org.postgresql:postgresql:9.4-1201-jdbc41")
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.3'
}
4

2 に答える 2

6

UserAccount のインスタンス化に使用されるクラスに Spring applicationContext を注入できます。

@Autowired
private ApplicationContext applicationContext;

次に、この方法で UserAccount Bean を作成します。

UserAccount userAccount = applicationContext.getBean(UserAccount.class);

このようにして、必要な依存関係を UserAccount クラスに注入できます。

于 2015-06-17T13:56:51.707 に答える
1

あなたの構成から、Spring が AOP を管理することを何らかの形で期待していると思います。ただし、@Autowired管理されていない Bean を探しているため、ロード時間ウィービングまたはコンパイル チーム ウィービングのいずれかを使用して自分でウィービングを行う必要があります。Spring は、デフォルトでメソッド レベルのアスペクトのみをサポートします。

9.8.4で説明されているように、読み込み時のウィービングには javaagent の使用が含まれるため(実稼働シナリオでは常に実用的であるとは限りません)、先に進んでコンパイル時のウィービングを使用しました。次のコードと構成は私にとってはうまくいきます。

ブート構成

@SpringBootApplication
@EnableSpringConfigured
public class App {
    public static void main(String[] args) {
        System.out.println("Hello World!");

        ApplicationContext ctx = SpringApplication.run(App.class, args);
        Account account = new Account();
        account.testConfigurable();
    }
}

Account.java

@Configurable(autowire = Autowire.BY_TYPE, dependencyCheck = true)
public class Account {

    @Autowired
    private SpringService service;

    public void testConfigurable() {
        System.out.println(service.returnHello());
    }
}

SpringService.java

@Service
public class SpringService {

    public String returnHello() {
        return "Hello";
    }

}

醜い pom.xml

<plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.7</version>
                <configuration>
                    <showWeaveInfo>true</showWeaveInfo>
                    <source>1.8</source>
                    <target>1.8</target>
                    <Xlint>ignore</Xlint>
                    <complianceLevel>1.8</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>1.8.5</version>
                    </dependency>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjtools</artifactId>
                        <version>1.8.5</version>
                    </dependency>
                </dependencies>
            </plugin>

以下は私が参考にしたリンクです。

  1. 春のドキュメントの9.8.1
  2. ここから Maven Config .

私は AOP の専門家ではないので、上記の方法で AOP を構成することによる通常の側面への影響については確信が持てません。ここでの議論。読み込み時間のウィービングがオプションである場合は、回答で説明されているように、先に進んでこれを使用する必要があります。

于 2015-06-18T06:11:31.293 に答える