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

版权声明:仅供学习交流使用 https://blog.csdn.net/drxRose/article/details/84965322
注解 释义
@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();
		}
	}

}

猜你喜欢

转载自blog.csdn.net/drxRose/article/details/84965322