20191230の春の公式文書(コア1.12)

1.12。Javaベースの構成コンテナ

1.12.1。基本的な考え方:@Beanと@Configuration

@Bean新しいオブジェクトを構成し、初期化するために、注釈を表示するための方法の例は、スプリングIoCコンテナによって管理されます。Springのに精通した者のための<beans/>XML構成の男、@豆やコメントの役割 同じ要素。あなたは、任意のためのバネができ @Component 、注釈付き@Bean使用。しかし、それらは最も一般的に関連付けられている @Configuration 豆で使用します。

@Configurationは、その主な目的ビーンソースとして定義されている注釈クラスを発現しました。さらに、@コンフィギュレーションクラスが同じクラスの別のメソッドの呼び出しによって@Beanビーン間の依存関係を定義することができます。

完全@Configurationと「ライト」@Beanモード?

使用されていない@Configurationは、クラスで宣言@Bean方法を注釈付きの場合、それらは「薄い」モードの処理と呼ばれています。@Component豆やクラス内で宣言しても一般的な方法では、「薄い」と考えられている、の主な目的は、異なるクラスが含まれ、および方法は、追加ボーナスがある@Bean。例えば、サービス管理コンポーネントは、各コンポーネントクラスに適用され、追加のビュー@Bean方法により容器に開示することができます。この場合、ビーンファクトリメソッド@メカニズムの一般的な方法です。

完全な、合理@Bean方法@Configuration異なるがビーン間の依存関係を宣言することはできません。その代わりに、彼らはその内部状態含むコンポーネント上で動作し、また記述することができるパラメータに従って動作することができます。したがって、このような方法は@Bean @Bean他の方法と呼ばれるべきではありません。確かに、これらの各方法は、特別なランタイムセマンティクスずに、単に特定の植物Bean参照するための方法です。ここで、正の影響はそれほどクラス設計に制限がない、ランタイムCGLIBサブクラスに適用すること、である(であるが、クラスが最終ことなどもできる含ま)。

、@豆の方法は、相互参照方法は、コンテナのライフサイクル管理にリダイレクトされますので、あなたは常に、「フル」モードを使用することを確実にするために、共通の@Configurationクラスの場合に宣言されます。これは、このように「ライト」モード追跡不可能な実行時の微妙な誤差を減らすために貢献し、予期せずに同じ@Bean呼び出し通常のJavaメソッドの呼び出しによって防ぐことができます。

1.12.2。春のコンテナAnnotationConfigApplicationContextの使用例

AnnotationConfigApplicationContext達成許容されるだけでなく、@Configuration入力とタイプは、一般的な受信することができる@Componentクラスをし、使用してJSR-330メタデータ注釈カテゴリ。

入力として@Configurationクラスを提供する場合、@コンフィギュレーションクラス自体はビーン定義として登録され、クラスもビーン定義として登録されるすべての@Bean方法で宣言されています。

そのメタデータDIこれらのクラス必要な場合、例えば、ビーン定義として登録され@ComponentおよびJSR-330型を提供し、それを仮定した場合@Autowired、または@Inject

// 基本用法
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);

// 手动注册配置类
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class, OtherConfig.class);
ctx.register(AdditionalConfig.class);
ctx.refresh();

// 以编程方式启用扫描功能
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.scan("com.acme");
ctx.refresh();

AnnotationConfigWebApplicationContextサポートWebアプリケーションで

<web-app>
    <!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext
        instead of the default XmlWebApplicationContext -->
    <context-param>
        <param-name>contextClass</param-name>
        <param-value>
            org.springframework.web.context.support.AnnotationConfigWebApplicationContext
        </param-value>
    </context-param>

    <!-- Configuration locations must consist of one or more comma- or space-delimited
        fully-qualified @Configuration classes. Fully-qualified packages may also be
        specified for component-scanning -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>com.acme.AppConfig</param-value>
    </context-param>

    <!-- Bootstrap the root application context as usual using ContextLoaderListener -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- Declare a Spring MVC DispatcherServlet as usual -->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext
            instead of the default XmlWebApplicationContext -->
        <init-param>
            <param-name>contextClass</param-name>
            <param-value>
                org.springframework.web.context.support.AnnotationConfigWebApplicationContext
            </param-value>
        </init-param>
        <!-- Again, config locations must consist of one or more comma- or space-delimited
            and fully-qualified @Configuration classes -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>com.acme.web.MvcConfig</param-value>
        </init-param>
    </servlet>

    <!-- map all requests for /app/* to the dispatcher servlet -->
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/app/*</url-pattern>
    </servlet-mapping>
</web-app>

1.12.3。@Beanコメントを使用します

あなたは、可能な@Configurationクラスまたは注釈付きの@Component使用注釈クラス@Beanのノートを。

ビーンの宣言

デフォルトでは、Beanのメソッド名と同じ名前。

することができます@Beanインターフェイス(または基本クラス)を使用するあなたの方法の型宣言を返します。

@Bean
public TransferService transferService() {
    return new TransferServiceImpl();
}

非不活性そのビーンインスタンス宣言順序単一の実施形態によれば、次の種類に応じて他の成分が一致は一例では、(例えば@Autowired TransferServiceImplを宣言されていないしようとしたときに応じて、検索結果の異なるタイプを参照することができるようのみ)transferService Beanの解決した後。

あなたは、サービスインタフェース宣言を通じて一貫タイプを参照する場合、@Bean戻り値の型は、安全設計上の決定事項に追加することができます。しかし、その潜在的なコンポーネントタイプの参照を達成するために、複数のインターフェイスまたはコンポーネントを達成するため、最も具体的なステートメントは、より安全な(少なくとも、必要な注入点の特定のタイプのようにBeanを参照して)タイプを返すことがあります。

豆依存性

@Bean
public TransferService transferService(AccountRepository accountRepository) {
    return new TransferServiceImpl(accountRepository);
}

ほぼ同じに基づいて分析コンストラクタ依存性注入メカニズム

ライフサイクルコールバックを受け取ります

従来のライフサイクルコールバック@Bean表記の定義を持つ任意のクラスのサポート、そしてあなたは、JSR-250に使用できる@PostConstruct@PreDestroyのコメントを。

春はまた、完全に通常のライフサイクルコールバックをサポートしています。豆を実装した場合InitializingBeanDisposableBeanまたはLifecycle、コンテナは、それぞれのメソッドを呼び出します。

また、完全に標準サポート*Awareインターフェース(例えばセットBeanFactoryAwareBeanNameAwareMessageSourceAwareApplicationContextAwareなど)。

@Bean注釈サポートは、Spring XMLのような、任意の初期化および破壊のコールバックメソッドを指定init-methodし、destroy-method次の例に示すように、bean要素の属性:

public class BeanOne {

    public void init() {
        // initialization logic
    }
}

public class BeanTwo {

    public void cleanup() {
        // destruction logic
    }
}

@Configuration
public class AppConfig {

    @Bean(initMethod = "init")
    public BeanOne beanOne() {
        return new BeanOne();
    }

    @Bean(destroyMethod = "cleanup")
    public BeanTwo beanTwo() {
        return new BeanTwo();
    }
}

デフォルトでは、共通の定義を有するJava設定を使用してclose、またはshutdown豆メソッドが自動的にコールバック破壊によって登録されます。あなたが公共のクローズまたはシャットダウン方法があり、コンテナが閉じられたときにそれを呼び出すにしたくない場合は、追加することができ@Bean(destroyMethod="")、デフォルト(無効にするには、Bean定義にinferred)モードを。

デフォルトでは、あなたは彼らのライフサイクルは、外部アプリケーションで管理されているので、JNDIリソースを介して取得するために、この操作が必要になります。具体的には、Java EEアプリケーションサーバ上の問題があるので確認は、DataSourceを常に動作させるために作ります。

データソース自動コールバックの破壊を防止する方法を次の例が示します:

@Bean(destroyMethod="")
public DataSource dataSource() throws NamingException {
    return (DataSource) jndiTemplate.lookup("MyDS");
}

また、@Bean方法のために、一般的に使用されるプログラミングJNDIルック方法が春を使用することであるJndiTemplateJndiLocatorDelegateのヘルパーを、または直接JNDIを使用しInitialContextますが、使用していないJndiObjectFactoryBean型を返すために、あなたを強制れる(バリアントをとして宣言されているFactoryBean、むしろ実際のターゲットタイプよりも、タイプこれは、本明細書で提供されるリソースを指すことを意図し、他@Bean方法で)ことが困難呼び出しを基準に交差することができます。

例えばBeanOneは、建設中に直接呼び出さコメント、前述のinit()方法を以下の例に示すように、同等に有効です。

@Bean
public BeanOne beanOne() {
    BeanOne beanOne = new BeanOne();
    beanOne.init();
    return beanOne;
}

あなたは、Javaを直接操作するときは、常にコンテナのライフサイクルに依存することなく、オブジェクト上の任意の操作を実行できます。

指定されたビーンのスコープ

デフォルトの範囲はあるsingletonが、あなたは使用することができ@Scope、次の例のように、それをカバーするために注釈を:

@Bean
@Scope("prototype")
public Encryptor encryptor() {
    // ...
}

春は依存スコープスコーププロキシプロセスで便利な方法を提供します。このようプロキシ設定を作成する最も簡単な方法は、XMLを使用することである<aop:scoped-proxy/>要素。使用@ScopeできるJava Bean構成で注釈をproxyMode同じサポート特性を提供します。デフォルト値は(エージェントレスであるScopedProxyMode.NO)、しかし、あなたは指定できますScopedProxyMode.TARGET_CLASSScopedProxyMode.INTERFACES

XMLドキュメントからの参照は、当社のJava @Beanに移植プロキシ例をスコープ場合、それは次のようになります。

// an HTTP Session-scoped bean exposed as a proxy
@Bean
@SessionScope
public UserPreferences userPreferences() {
    return new UserPreferences();
}

@Bean
public Service userService() {
    UserService service = new SimpleUserService();
    // a reference to the proxied userPreferences bean
    service.setUserPreferences(userPreferences());
    return service;
}

カスタムBean名

デフォルトでは、クラスを使用するように設定@Bean、Beanのメソッドの結果の名前として名前を。ただし、使用することができname、次の例に示すように、属性は、この機能を無効にします:

@Bean(name = "myThing")
public Thing thing() {
    return new Thing();
}

豆の別名

別名と呼ばれる単一豆、豆のために複数の名前を提供することが望ましい場合があります。この目的のため、@Beanコメントはname文字列の配列プロパティを受け入れます。エイリアス豆を複数設定する方法次の例が示します:

@Bean({"dataSource", "subsystemA-dataSource", "subsystemB-dataSource"})
public DataSource dataSource() {
    // instantiate, configure and return DataSource bean...
}

ビーンの説明

いくつかのケースでは、より詳細なテキスト記述がBeanについて参考になる提供しています。監視する(おそらくJMXを介して)Beanを露光するとき、それは特に有用です。

説明を追加するために@Bean使用することが@Description次の例に示すように、注釈:

@Bean
@Description("Provides a basic example of a bean")
public Thing thing() {
    return new Thing();
}

1.12.4。使用@Configurationコメント

@Configurationこれは、オブジェクトがソースビーンによって定義されていることを示すクラスレベルの注釈です。公共@Beanコメントによって@Configuration Beanクラスのメソッド宣言。@Bean @Configurationクラスのメソッド呼び出しはまた、ビーン間の依存関係を定義するために使用されてもよいです。

豆の間に注入するの依存関係

豆の相互依存は、別のBeanメソッドへの呼び出しを行うように依存関係が表すとき、次の例のように、単純に依存しています。

@Configuration
public class AppConfig {

    @Bean
    public BeanOne beanOne() {
        return new BeanOne(beanTwo());
    }

    @Bean
    public BeanTwo beanTwo() {
        return new BeanTwo();
    }
}

宣言メソッド@Bean @Configurationクラスは、この宣言豆相互依存関係の方法が機能した場合のみ。あなたは、通常の@Componentクラス宣言ビーン間の依存関係を使用することはできません。

メソッド・インジェクションを探します

先に述べたように、注入法のための外観は高度な機能である、あなたはめったに使うべきではありません。単一の実施形態では、豆依存プロトタイプ・スコープBeanをスコープこれは有用です。このタイプの構成のためのJavaは、このパターンを実現する自然な方法を提供します。Findメソッドインジェクションの使用方法次の例が示します:

public abstract class CommandManager {
    public Object process(Object commandState) {
        // grab a new instance of the appropriate Command interface
        Command command = createCommand();
        // set the state on the (hopefully brand new) Command instance
        command.setState(commandState);
        return command.execute();
    }

    // okay... but where is the implementation of this method?
    protected abstract Command createCommand();
}

Java設定を使用することで、カバー抽象的な作成できるcreateCommand()方法CommandManager何らかの方法で新しい(プロトタイプ)コマンドオブジェクトを見つけるサブクラスを、。これを行う方法を次の例が示します:

@Bean
@Scope("prototype")
public AsyncCommand asyncCommand() {
    AsyncCommand command = new AsyncCommand();
    // inject dependencies here as required
    return command;
}

@Bean
public CommandManager commandManager() {
    // return new anonymous implementation of CommandManager with createCommand()
    // overridden to return a new prototype Command object
    return new CommandManager() {
        protected Command createCommand() {
            return asyncCommand();
        }
    }
}

内作業方法のJavaベースの構成の詳細については、

この例が示すが@Beanアノテーションを付けるメソッドが2回呼び出され、次の例を考えてみます。

@Configuration
public class AppConfig {

    @Bean
    public ClientService clientService1() {
        ClientServiceImpl clientService = new ClientServiceImpl();
        clientService.setClientDao(clientDao());
        return clientService;
    }

    @Bean
    public ClientService clientService2() {
        ClientServiceImpl clientService = new ClientServiceImpl();
        clientService.setClientDao(clientDao());
        return clientService;
    }

    @Bean
    public ClientDao clientDao() {
        return new ClientDaoImpl();
    }
}

新しいclientDaoのインスタンス()メソッドはClientDaoImplを作成し、それを返すので、2つのインスタンス(各サービスA)を有することが望ましいことが多いです。これは間違いなく問題です:春、インスタンス化されたBeanは、デフォルトでシングルトンスコープを持っています。スタートアップ@Configuration使用CGLIBサブクラスですべてのクラス:これは魔法の場所です。メソッドを呼び出す前に、サブカテゴリー、サブ方法では、親と、Beanコンテナのいずれかのキャッシュ(スコープ)があるかどうか、最初のチェックの新しいインスタンスを作成します。

豆の範囲によれば、動作は異なっていてもよいです。ここでは、単一のケースについて話しています。

CGLIBクラスが再パッケージ化されたため、春3.2以降、CGLIBはもはや、あなたのクラスパスに追加する必要はありませんorg.springframework.cglib下と直接に含まspring-coreJAR。

CGLIBを動的に起動時に機能を追加するので、ので、いくつかの制限があります。具体的には、クラスが配置することができませんfinalの。ただし、バージョン4.3以降、単一または@Autowiredの使用を含むコンストラクタ、に基づいて、任意の構成の使用を可能にすると、デフォルトの注射のための非デフォルトコンストラクタ宣言しました。

あなたはCGLIBを課される制約を回避したい場合は、(例えば、共通@Componentクラスに宣言された)非@コンフィギュレーションクラスにあなたの方法@Bean宣言をご検討ください。その後@Bean方法はインターセプトメソッド呼び出しの間で交差しないので、あなたは、依存性注入のどこコンストラクタまたはメソッドレベルのみに依存する必要があります。

1.12.5。Javaベースの構成物の組成

春のJavaベースの設定機能を使用すると、設定の複雑さを軽減することができ、注釈を書き込むことができます。

使用@importコメント

スプリングXMLファイルで使用されるような<import/>同一のモジュール構成を支援するための要素、@Import注釈を示すクラスからロードされた構成の他の例として、@Bean定義を可能にします。

@Configuration
public class ConfigA {

    @Bean
    public A a() {
        return new A();
    }
}

@Configuration
@Import(ConfigA.class)
public class ConfigB {

    @Bean
    public B b() {
        return new B();
    }
}

インポート@スプリングフレームワーク4.2を開始することも同様の従来のコンポーネントクラスを参照し、サポートAnnotationConfigApplicationContext.register方法。あなたが明示的に組み立てスキャンを回避するように、いくつかの種類の設定を使用してエントリポイントとして、すべてのコンポーネントを定義する場合、この機能は特に便利です。

インポート定義さ@Beanに注入依存性

@Configuration
public class ServiceConfig {

    @Bean
    public TransferService transferService(AccountRepository accountRepository) {
        return new TransferServiceImpl(accountRepository);
    }
}

@Configuration
public class RepositoryConfig {

    @Bean
    public AccountRepository accountRepository(DataSource dataSource) {
        return new JdbcAccountRepository(dataSource);
    }
}

@Configuration
@Import({ServiceConfig.class, RepositoryConfig.class})
public class SystemTestConfig {

    @Bean
    public DataSource dataSource() {
        // return new DataSource
    }
}

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
    // everything wires up across configuration classes...
    TransferService transferService = ctx.getBean(TransferService.class);
    transferService.transfer(100.00, "A123", "C456");
}

同じ結果を達成するための別の方法があります。覚えて、覚えて、@Configurationクラス最終的にはちょうど別のBeanコンテナ:彼らは使用することができ、この手段@Autowiredために@Value同じ機能を他のBeanを注入します。

このように、依存性注入は、最も単純なものです。コンテキスト初期化プロセス@Configuration初期の授業中、および注入の依存関係に強制的にこのように予想外の早期初期化を引き起こす可能性があります。図示のように、注入パラメータが可能基づきます。

また、特別な注意を払ってくださいBeanPostProcessorBeanFactoryPostProcessor@Beanを定義しました。これは、通常、それらの宣言であるべきであるstatic @Bean構成を含むクラスのインスタンスをトリガーすることなく、方法。それ以外の場合は、Autowiredと@value @ない構成作業のようにそれは早すぎるBeanインスタンスとして作成されるため。

@Configuration
public class ServiceConfig {

    @Autowired
    private AccountRepository accountRepository;

    @Bean
    public TransferService transferService() {
        return new TransferServiceImpl(accountRepository);
    }
}

@Configuration
public class RepositoryConfig {

    private final DataSource dataSource;

    public RepositoryConfig(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Bean
    public AccountRepository accountRepository() {
        return new JdbcAccountRepository(dataSource);
    }
}

@Configuration
@Import({ServiceConfig.class, RepositoryConfig.class})
public class SystemTestConfig {

    @Bean
    public DataSource dataSource() {
        // return new DataSource
    }
}

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
    // everything wires up across configuration classes...
    TransferService transferService = ctx.getBean(TransferService.class);
    transferService.transfer(100.00, "A123", "C456");
}

春のフレームワーク4.3サポートからのみ@Configurationクラスのコンストラクタ・インジェクションを開始します。また、ターゲットBeanのみ@Autowiredを指定せずにコンストラクタを定義している場合ことに注意してください。

@Configurationクラスまたは条件@Bean前記

いくつかの任意のシステム状態に基づいて、条件付きで有効または無効に完全に1つでも@Bean @Configurationクラスメソッドは、多くの場合に便利です。春の環境で特定のプロファイル際の一般的な例にのみ有効に使用されている@Profileコメントは、豆を活性化させます。

@Profileコメントはより柔軟な使用によって呼び出され@Conditionalたアノテーション実際の実装。

Conditionインタフェースの実装は、提供matches(..)方法がtrueまたはfalseを返します。

JavaとXMLコンフィギュレーションの組み合わせ

Springのサポート@Configurationクラスは完全に100%春のXMLに代わるものではありません。(例えば、春のXML名前空間のための)いくつかのツールは、コンテナの構成に理想的な方法のまま。状況下でXMLまたは必要に応じて使用して簡単に、あなたが選択することができます:使用ClassPathXmlApplicationContextコンテナをインスタンス化するには、「XML中心」のアプローチ、またはAnnotationConfigApplicationContext「Java中心の」インスタンス化コンテナを経由しています。@ImportResource必要に応じて注釈は、XMLをインポートすることができます。

@ConfigurationクラスのXML中心の使用

@Configurationクラス宣言は、純粋な春のある<bean/>要素

<beans>
    <context:annotation-config/>
    <bean class="com.acme.AppConfig"/>
</beans>

使用<context:component-scan />ピックアップ@Configurationクラス

この場合、当社は明示的に宣言する必要はありません<context:annotation-config/>ので、<context:component-scan/>同じ機能が有効になっています。

<context:component-scan base-package="com.acme"/>

@Configurationクラス中心のXMLおよび@ImportResourceへ

@ImportResource("classpath:/com/acme/properties-config.xml")

properties-config.xml
<beans>
    <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
</beans>

することで@PropertySourceプロパティファイルを導入

おすすめ

転載: www.cnblogs.com/huangwenjie/p/12121368.html