Spring注解开发(一)组件注册

 

Spring组件注册就是让Spring的IOC容器去管理组件的这个bean,

SPring组件基于注解的注册方法主要有以下几种:

首先需要一个@Configuration注解的配置类,告诉Spring容器配置的入口,和xml配置文件的功能一样

一:@Bean

首先新建一个Person类,属性为String:name,Integer:age;

新建配置类,代码如下:

@Configuration//表示当前类为一个配置类
public class MainConfig01 {
	@Bean
	public Person person() {
		return new Person("Alen", 18);
	}
}

测试类如下:

@Test
public void test01() {
	AnnotationConfigApplicationContext applicationContext = new 
         AnnotationConfigApplicationContext(MainConfig01.class);
		String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
		for (String name : beanDefinitionNames) {
			System.out.println(name);
		}
	}

打印出来容器中的组件除了Spring本身自带的还有这两个: mainConfig01  person

  1. @Bean默认beanDefinitionName为方法名,也可以指定@Bean("Alen")
  2. @Bean 和xml文件配置中的<Bean>标签一致,也可以指定以下属性

           2.1.默认为单例模式,scope可以指定单例还是多例,单例默认在容器创建是创建组件并放入容器,多例则在获取时创建

           2.2指定init-method和destory-method,单例下Bean的生命周期交给容器管理,init-method和destory-method都会执行,多例下只     会执行destory-method

           2.3.@Lazy注解,组件会在容器获取时初始化创建。

二:@ComponentScan+@Component(@Service,@Repository,@Controller)

            包扫描+组件注解,@ComponentScan中可以指定要扫描的包中加注了组件注解的类

在@ComponentScan注解中,

1.默认会自动扫描以下四个注解注解的组件

/**
 * Indicates whether automatic detection of classes annotated with {@code @Component}
 * {@code @Repository}, {@code @Service}, or {@code @Controller} should be enabled.
 */
boolean useDefaultFilters() default true;

2.标签值为@Filter的两个过滤器

Filter[] excludeFilters() default {};//排除
Filter[] includeFilters() default {};//包含

值为@Filter,默认的过滤类型为注解格式,

/**
 * The type of filter to use.
 * <p>Default is {@link FilterType#ANNOTATION}.
 * @see #classes
 * @see #pattern
 */
FilterType type() default FilterType.ANNOTATION;

在Filter Type枚举类型中还有其他几个格式

public enum FilterType {	
    // Filter candidates marked with a given annotation.
	ANNOTATION,//按照注解过滤
	// Filter candidates assignable to a given type.
	ASSIGNABLE_TYPE,//按照类型过滤
	// Filter candidates matching a given AspectJ type pattern expression.
	ASPECTJ,//使用ASPECTJ表达式
	// Filter candidates matching a given regex pattern.
	REGEX,//按照正则过滤
	//Filter candidates using a given custom
	CUSTOM//按照用户自定义
}

按照自定义的规则

{@link org.springframework.core.type.filter.TypeFilter} implementation.

我们需要去实现TypeFilter接口,举个例子,代码如下:

public class MyFliterType implements TypeFilter {
	@Override
	public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
			throws IOException {
		ClassMetadata classMetadata = metadataReader.getClassMetadata();
		String className = classMetadata.getClassName();
		//此处只测试是否匹配扫描的类名包含Demo
		if (className.contains("Demo")) {
			return true;
		}
		return false;
	}
}

配置类如下:

@Configuration
@ComponentScan(value = "com.practice.bean")
public class MainConfig01 {
	@Bean
	public Person person() {
		return new Person("Alen", 18);
	}
}

 

测试类:

@Test
public void test02() {
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig01.class);
		String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
		for (String name : beanDefinitionNames) {
			System.out.println(name);
		}

	}

结果为:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig01
controllerDemo
daoDemo
serviceDemo
person
  • 1。@ComponentScan(value = "com.practice.bean",  excludeFilters = {@Filter(type = FilterType.CUSTOM, classes = { Controller.class}) }),将Controller注解的组件排除在外,controllerDemo将不会注册
  • 2。@ComponentScan(value = "com.practice.bean", useDefaultFilters = false)将使用默认的过滤器开关置为false,则@Component(@Service,@Repository,@Controller)四个注解的组件将不会自动扫描注册
  • 3.@ComponentScan(value = "com.practice.bean",  excludeFilters = {@Filter(type = FilterType.CUSTOM, classes = { MyFliterType.class}) }),根据自定义规则包含Demo的组件将不会被注册

includeFilters此处不再讲解,需要将useDefaultFilters = false置为false,因为默认开启会扫描Componernt四个注解。

 

三。@Conditional按照条件加载,满足条件则会加载

自定义一个条件,需要实现Condition类,代码如下

public class MyCondition implements Condition {
	@Override
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		Environment environment = context.getEnvironment();
		String property = environment.getProperty("os.name");
		if (property.contains("Windows")) {
			return true;
		}
		return false;
	}
}

此类的意思是在操作系统在Windows环境下则加载

 在扫描的com.practice.bean包中加了@Component注解的某个类上加上@Conditional(value = MyCondition.class)注解

我们将启动参数改为-Dos.name=Linux,则此组件将不会再被注册。

 

四。@Import(value = {  })导入组件

      1. 直接导入

       在bean的包下先建一个 MyImport类,我们将此注解@Import(value = { MyImport.class })加在我们的主配置类上,执行测试类,

可以看到,输出的组件中包含了该类的全类名(默认ID为全类名)。

      2.ImportSelector:导入组件选择器,

   2.1实现接口ImportSelector:

public class MyImportSelector implements ImportSelector {
	@Override
	public String[] selectImports(AnnotationMetadata importingClassMetadata) {
		//importingClassMetadata.getClassName()为配置类
		return new String[] { "com.practice.bean.MyImport" };
	}
}

配置类注解@Import(value = {MyImportSelector.class }),执行测试类,可以看到MyImport组件已注册

  2.2ImportBeanDefinitionRegistrar:导入组件定义注册器

作用:实现ImportBeanDefinitionRegistrar接口,我们可以为容器注册组件。

   新建ImportBeanDefinitionRegistrarTest类以做测试:

public class ImportBeanDefinitionRegistrarTest{
}

  新建MyImportBeanDefinitionRegistrar类,为容器注册ImportBeanDefinitionRegistrarTest类的Bean定义信息,导入该组件。

 代码如下:

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		RootBeanDefinition beanDefinition = new RootBeanDefinition(ImportBeanDefinitionRegistrarTest.class);
		registry.registerBeanDefinition("importBeanDefinitionRegistrarTest", beanDefinition);
	}
}

     配置类注解改为@Import(value = {MyImportSelector.class,MyImportBeanDefinitionRegistrar.class }),执行测试类,可以看到importBeanDefinitionRegistrarTest组件已注册。

五。使用FactoryBean注册组件

FactoryBean实现类如下:

public class MyFactoryBean implements FactoryBean<Person> {
	@Override
	public Person getObject() throws Exception {
		return new Person();
	}
	@Override
	public Class<?> getObjectType() {
		return Person.class;
	}
}

配置类修改为

@Configuration
@ComponentScan(value = "com.practice.bean")
public class MainConfig01 {
	@Bean
	public MyFactoryBean MyFactoryBean() {
		return new MyFactoryBean();
	}
}

运行测试类,可以看到MyFactoryBean已被注册。那么这个MyFactoryBean就是MyFactoryBean类吗?

我们在测试类中加上:

Object bean = applicationContext.getBean("MyFactoryBean");
System.out.println(bean);

打印出的bean为com.practice.bean.Person类,说明Person已被注册到容器中。

那么怎么获取这个MyFactoryBean类组件呢,使用&符号,源码中已给出说明。

/**
 * Used to dereference a {@link FactoryBean} instance and distinguish it from
 * beans <i>created</i> by the FactoryBean. For example, if the bean named
 * {@code myJndiObject} is a FactoryBean, getting {@code &myJndiObject}
 * will return the factory, not the instance returned by the factory.
 */
String FACTORY_BEAN_PREFIX = "&";

 Object bean = applicationContext.getBean("&MyFactoryBean");

打印bean.getClass.Console显示class com.practice.bean.MyFactoryBean。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值