1. 程式人生 > >spring ioc---基於註解的配置(context包,@Configuration,@Bean,etc)

spring ioc---基於註解的配置(context包,@Configuration,@Bean,etc)

註解 釋義
@Configuration

宣告一個基於java註解的配置類物件.一般和@Bean組合使用,當然根據不同的場景,可配合其他多種註解使用.

原始碼(部分)文件:Indicates that a class declares one or more @Bean methods and may be processed by the Spring container to generate bean definitions and service requests for those beans at runtime.

@Bean

使用此標註,表示為容器註冊一個bean,相當於xml配置檔案中的bean標籤.

原始碼(部分)文件:Indicates that a method produces a bean to be managed by the Spring container.

@ComponentScan

使用此標註,表示開啟註解掃描,相當於xml配置檔案中的<context:component-scan>標籤.

原始碼(部分)文件:Configures component scanning directives for use with @Configuration classes. Provides support parallel with Spring XML's <context:component-scan> element.

@ComponentScans[✘]

聚合多個註解掃描器,相當於xml配置檔案中配置多行開啟註解掃描器的標籤.其預設值儲存的是ComponentScan型別的陣列.

原始碼(部分)文件:Container annotation that aggregates several ComponentScan annotations.

@Primary

當存在同一類物件多個bean配置的時候,獲取bean例項不明確的時候,設定首選bean.

原始碼(部分)文件:Indicates that a bean should be given preference when multiple candidates are qualified to autowire a single-valued dependency. If exactly one 'primary' bean exists among the candidates, it will be the autowired value.

@Scope

配置bean的作用域,相當於xml配置檔案中bean標籤的scope屬性.

另,在web包中,有針對不同作用域的建議配置註解,例如@RequestScope,@SessionScope,e.g.

原始碼(部分)文件:When used as a type-level annotation in conjunction with @Component,@Scope indicates the name of a scope to use for instances of the annotated type.When used as a method-level annotation in conjunction with @Bean,@Scopeindicates the name of a scope to use for the instance returned from the method.

@Lazy

設定配置的bean為懶載入.等價於xml配置檔案中bean標籤中的lazy-init的屬性.

原始碼(部分)文件:Indicates whether a bean is to be lazily initialized.

@Description 設定容器中配置bean的描述資訊,從版本4.3新增註解.提取描述資訊的時候,使用BeanDefinition類的方法.原始碼(部分)文件:Adds a textual description to bean definitions derived from
@Role 定義容器中bean的身份,不常用,通常bean的等級為0.類物件BeanDefinition中內建的對映常量.原始碼(部分)文件:Indicates the 'role' hint for a given bean.
@Conditional 設定容器註冊bean的條件限制,滿足容器則註冊,否則不予註冊.定製的條件限制需要實現Condition介面實現.註解@Profile就是借用此介面實現的.原始碼(部分文件):Indicates that a component is only eligible for registration when all specified conditions match.
@Profile[✘]

Indicates that a component is eligible for registration when one or more specified profiles are active.

@DependsOn[✘] 注入依賴關係不直接的bean使用,相當於xml配置檔案中bean標籤的depends-on屬性.原始碼(部分)文件:Beans on which the current bean depends. Any beans specified are guaranteed to be created by the container before this bean. Used infrequently in cases where a bean does not explicitly depend on another through properties or constructor arguments, but rather depends on the side effects of another bean's initialization.
@Filter[✘] 一般配合註解@ComponentScan使用.原始碼(部分)文件:Declares the type filter to be used as an include filter or exclude filter.
@Import[✘]

Indicates one or more @Configuration classes to import.

@ImportResource[✘]

Indicates one or more resources containing bean definitions to import.

@PropertySource[✘]

Annotation providing a convenient and declarative mechanism for adding a PropertySource to Spring's Environment. To be used in conjunction with @Configuration classes.

@PropertySources[✘]

Container annotation that aggregates several PropertySource annotations.

@EnableAspectJAutoProxy[✘]

Enables support for handling components marked with AspectJ's @Aspect annotation, similar to functionality found in Spring's <aop:aspectj-autoproxy> XML element. To be used on @Configuration classes as follows:

@EnableLoadTimeWeaving[✘]

Activates a Spring LoadTimeWeaver for this application context, available as a bean with the name "loadTimeWeaver", similar to the <context:load-time-weaver> element in Spring XML.

@EnableMBeanExport[✘]

Enables default exporting of all standard MBeans from the Spring context, as well as well all @ManagedResource annotated beans.

@EnableSrpingConfigured[✘]

Signals the current application context to apply dependency injection to non-managed classes that are instantiated outside of the Spring bean factory (typically classes annotated with the @Configurable annotation).

備忘,表格中註解後面沒有新增`[✘]`,是程式碼測試的部分註解.


測試bean的類物件

package siye;
public class MemberCls
{
	public void init()
	{
		System.out.println("bean_init...");
	}
}

容器的配置類

package siye;

import java.util.Map;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Description;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Role;
import org.springframework.context.annotation.Scope;
import org.springframework.core.type.AnnotatedTypeMetadata;


/*
 * 1,註解configuration:標註此類是基於java註解的配置類,
 * 		相當於xml配置檔案中的beans標籤.
 * 		另,此類的配置資訊可通過ApplicationContext的實現類註冊.
 * 2,註解bean:標註此方法用來定義一個bean,
 * 		相當於xml配置檔案的bean標籤.
 * 3,註解componentScan:開啟註解掃描
 * 		相當於xml配置檔案中的<context:component-scan>標籤.
 * 		另版本4.3開始,新增註解componentScans,其預設值型別是
 * 		註解componentScan陣列,即聚合多個註解掃描器.
 * 		相當於xml配置檔案中定義多行對等的標籤.
 * 
 * 一般在基於java註解的配置類中,建議使用configuration和bean的組合方式.
 * 當然也存在其他的配置方式.
 */
@Configuration
@ComponentScan("siye")
public class ConfigClass
{

	/*
	 * 註解primary
	 * 當容器對同一類物件定義兩個以上的bean標識的時候,
	 * 容器獲取該類物件例項的時候未提供明確依據,
	 * 使用註解primary,即可設定該bean未首選的
	 */
	@Primary
	@Bean("annoPrimary")
	public String annoPrimary()
	{
		return new String();
	}



	/*
	 * 
	 * 註解scope
	 * 1,預設值value(即scopeName),有四個候選值,
	 * 即singleton,prototype,requestScope,sessionScope
	 * 可使用ConfigurableBeanFactory和WebApplicationContext
	 * 中內建的常量.
	 * 2,值proxyMode
	 * 儲存型別為ScopedProxyMode,即等價於xml配置檔案中的標籤:
	 * <aop:scoped-proxy/>
	 * 3,版本4.3開始,此註解擴充套件了兩個建議註解,即註解requestScope
	 * 和註解sessionScope.
	 * 
	 * 當只是用預設值配置的時候,相當於bean標籤中的scope屬性,
	 * 管理bean的作用域.
	 */
	@Bean("annoScope")
	@Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
	public String annoScope()
	{
		return new String();
	}



	/*
	 * 註解lazy
	 * 配置bean是否懶載入
	 * 值value的預設值true
	 */
	@Bean(name = "annoLazy", initMethod = "init")
	@Lazy
	public MemberCls annoLazy()
	{
		return new MemberCls();
	}


	/*
	 * 註解description
	 * 對容器中管理的bean的描述資訊,配合componpent和bean註解使用.
	 * 最低版本要求4.0
	 */
	@Bean("annoDesc")
	@Description("this's_test_anno_description")
	public String annoDesc()
	{
		return new String();
	}


	/*
	 * 註解role
	 * 標註容器中存在的bean的身份.
	 * 可使用BeanDefinition中的常量表示,
	 * 0,表示使用者建立的bean
	 * 1,支援容器正常執行的配置bean
	 * 2,表示後臺容器工作必備的bean
	 */
	@Bean("annoRole")
	@Role(value = BeanDefinition.ROLE_APPLICATION)
	public String annoRole()
	{
		return new String();
	}


	/*
	 * 註解conditional
	 * 條件限制,滿足條件,則讓容器註冊該bean,不滿足的話,
	 * 什麼也不做.
	 * 補充註解,profile就是使用該特性實現的.
	 * 
	 * 若註解bean的name值不是annoConditional,
	 * 則容器不會註冊該bean.
	 */
	@Bean("annoConditional")
	@Conditional(MyConditional.class)
	public String annoConditional()
	{
		return new String("test_annoConditional");
	}



}

/*
 * 定製條件限制
 * 使用註解bean,且其name值是annoConditional,
 * 即允許容器註冊該bean.
 * 否則不予註冊.
 */
class MyConditional implements Condition
{

	@Override
	public boolean matches(ConditionContext context,
			AnnotatedTypeMetadata metadata)
	{
		if (context.getEnvironment() != null)
		{
			if (metadata.getAnnotationAttributes(Bean.class.getName()) != null)
			{
				Map<String, Object> map =
						metadata.getAnnotationAttributes(Bean.class.getName());
				String[] arr = (String[]) map.get("name");
				int index = 0;
				while (true)
				{
					if ("annoConditional".equals(arr[index]))
					{
						return true;
					}
					index++;
					if (index >= arr.length)
					{
						return false;
					}
				}
			}
		}
		return false;
	}

}

測試類

package siye;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class UnitTest
{

	private AnnotationConfigApplicationContext context;

	@Before
	public void init()
	{
		context = new AnnotationConfigApplicationContext();
		context.register(ConfigClass.class);
		context.refresh();
	}


	@Test
	public void testPrimary()
	{
		// 若未設定首選的bean,則丟擲異常NoUniqueBeanDefinitionException
		String obj = context.getBean(String.class);
		System.out.println(obj.hashCode());
	}


	@Test
	public void testScope()
	{
		// 驗證註解scope
		String bean0 = context.getBean("str1", String.class);
		String bean1 = context.getBean("str1", String.class);
		System.out.println(bean0 == bean1);
	}

	@Test
	public void testLazy()
	{
		System.out.println(context);
		// 呼叫次方法的時候,才初始化該bean,並回調初始化方法.
		// context.getBean("annoLazy", MemberCls.class);
	}


	@Test
	public void testDesc()
	{
		BeanDefinition beanDefinition = context.getBeanDefinition("annoDesc");
		String result = beanDefinition.getDescription();
		System.out.println(result);
	}


	@Test
	public void testRole()
	{
		int result = context.getBeanDefinition("annoRole").getRole();
		System.out.println(result);
	}


	@Test
	public void testConditional()
	{
		String obj = context.getBean("annoConditional", String.class);
		System.out.println(obj);
	}


	@After
	public void destroy()
	{
		if (context != null)
		{
			context.close();
		}
	}

}