LoginSignup
10
14

More than 5 years have passed since last update.

spring管理beanをpojoから呼び出す

Posted at

やりたいこと

springで管理されていないクラスからspring管理beanを呼び出したいケースがたまにあるので、実装方法をまとめる。

環境

java8
javaee7
spring4.3.9
eclipse4.6

実装案

  • Spring管理beanにstaticアクセス
  • @Configurable
  • SpringBeanAutowiringInterceptor

※3つ目はJavaEEに限った方法なので注意。

呼び出したいサービス

呼び出したいサービス
package com;

import org.springframework.stereotype.Service;

@Service
public class TestService {
    public void execute(){
        System.out.println("com.TestService#execute");
    }
}

案1 Spring管理beanにstaticアクセス

ApplicationContextを保持したSpring管理beanを作成して、pojoからstaticメソッド経由でアクセスする。

ApplicationContextを保持するSpring管理bean
package com.bridge;

import com.TestService;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringContextBridge implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Autowired
    private TestService testService;

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public static SpringContextBridge getInstance() {
        return applicationContext.getBean(SpringContextBridge.class);
    }

    public TestService getTestService() {
        return testService;
    }
}
pojoクラス
package com.bridge;

public class SpringContextBridgeClient {
    public static void main(String[] args) {
        SpringContextBridge.getInstance().getTestService().execute();
    }
}

参考サイト
https://blog.jdriven.com/2015/03/using-spring-managed-bean-in-non-managed-object/

案2 @Configurable

AspectJを使ってコンパイル時に、@Configurableを付けたクラスをnewしている個所を差し替える(たぶん。ソース確認したわけではないので推測)。

@Configurableでspring管理beanになるクラス
package com.configurable;

import com.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;

@Configurable
public class ConfigurableClient {

    @Autowired
    private TestService testService;

    public void execute() {
        testService.execute();
    }
}
pojoクラス
package com.configurable;

public class Configurable {
    public static void main(String[] args) {
        // newで生成してもDIされる!
        new ConfigurableClient().execute();
    }
}
application-context.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
                           http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
                           http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">
    <context:spring-configured/>
    <context:component-scan base-package="com.configurable"/>
    <context:annotation-config />
</beans>
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>test1</groupId>
  <artifactId>artifact1</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>artifact1</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <aspectj.version>1.6.12</aspectj.version>
    <spring.version>4.3.9.RELEASE</spring.version>
  </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${aspectj.version}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${aspectj.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>persistence-api</artifactId>
            <version>1.0.2</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.4</version>
                <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>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <aspectLibraries>
                        <aspectLibrary>
                            <groupId>org.springframework</groupId>
                            <artifactId>spring-aspects</artifactId>
                        </aspectLibrary>
                    </aspectLibraries>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

mavenでcompileと実行
mvn clean compile
mvn exec:java -Dexec.mainClass="com.configurable.Configurable"

mavenコマンドではなくeclipseで実行したい場合

eclipseでpom.xmlを開くと下記エラー出ているはず。

ライフサイクル構成でカバーされていないプラグインの実行: org.codehaus.mojo:aspectj-maven-plugin:1.4:compile (実行: default, phase: compile)

aspectjのcompileを使えるようにAJDTを入れやる必要がある。

AJDTインストール

※他のオプションも一緒にインストールしたら後続手順でエラーになったので、いったんAJDTだけ入れるのがよさそう

  • pom.xmlのエラー個所をクリックして 「新規 m2eコネクターを発見する」でコネクターをインストール

これで実行できる!

参考サイト
http://ryu-htn.hatenablog.com/entry/2013/04/25/151240
https://github.com/kenyattaclark/Spring-Configurable-Example
https://tamasgyorfi.net/2013/11/13/spring-dependency-injection-configurable/

参考サイト(eclipseエラー)
http://tyru.hatenablog.com/entry/20140905/eclipse_lifecycle_error

案3 SpringBeanAutowiringInterceptor

JavaEEのInterceptorと、SpringのSpringBeanAutowiringInterceptorを使う。
下記はEJBクラスをSpring管理Beanにした例。
(もちろんEJBじゃなくてもOK。@Stateless, @RemoteはEJBのアノテーションなので消してOK)

EJBクラス
package com.autowired;

import com.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor;

import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;

@Stateless
@Remote
@Interceptors(SpringBeanAutowiringInterceptor.class)
public class TestEjb {

    @Autowired
    private TestService testService;

    public void execute() {
        testService.execute();
    }
}

評価

  • javaEEを使っているなら「案3 SpringBeanAutowiringInterceptor」が一番シンプルで良いと思う。
  • javaEEを使っていないなら「案1 Spring管理beanにstaticアクセス」が良いと思う。

※初めは「案2 @Configurable」が良さそうに見えたが、すべてのnewを差し替えるのは何か課題がありそう(テストモックとか)。
AspectJのライブラリが追加が必要な点も考慮すると「案1 Spring管理beanにstaticアクセス」のほうがシンプルで良さそう。

10
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
14