Spring注解驱动开发-part1组件注册

本文详细介绍了在Spring框架中注册和实例化Bean的多种方法,包括基于XML配置、使用@Configuration注解、通过@ComponentScan指定扫描范围、设置Bean作用域、使用@Conditional按条件注册及利用@Import和FactoryBean导入组件。

基于XML配置的方式

先注册一个Bean

	<bean id="person" class="com.EzerbelCN.bean.Person">
		<property name="id" value="1"></property>
		<property name="name" value="Lilith"></property>
		<property name="gender" value="1"></property>
	</bean>

然后取出实例

@Test
	public void test01() {
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
		Person person = (Person)context.getBean("person");
		System.out.println(person);
		context.close();
	}

使用@Configuration注册配置类

//配置类==配置文件
@Configuration
public class MainConfig {
	//给容器中注册一个Bean;类型为返回值类型,id默认为方法名
	@Bean 
	public Person person() {
		return new Person(2,"Jerry",1);
	}
	//-------------------------使用别名-------------------------
	@Bean("car01")
	public Car car() {
		return new Car("Farrari", 9999f);
	}
}

使用应用的注解配置上下文来获得注册的Bean实例:

	@Test
	public void test02() {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
		Person person = (Person)context.getBean("person");
		System.out.println(person);
		Car car = (Car)context.getBean("car01");
		System.out.println(car);
		context.close();
	}
  • 使用ComponentScan来指定扫描范围

    type=FilterType.ANNOTATION 按照注解类型进行过滤
    useDefaultFilters=false 不使用默认的过滤器

@Configuration
@ComponentScan(value="com.EzerbelCN",includeFilters= {
		@Filter(type=FilterType.ANNOTATION,classes= {Controller.class})
},useDefaultFilters=false)
public class MainConfig {
	//给容器中注册一个Bean;类型为返回值类型,id默认为方法名
	@Bean 
	public Person person() {
		return new Person(2,"Jerry",1);
	}
	//使用别名
	@Bean("car01")
	public Car car() {
		return new Car("Farrari", 9999f);
	}
}

ComponentScan属于可重复注解:
在这里插入图片描述

因此可以使用多个@ComponentScan,增加不同的扫描策略,也可以使用ComponentScans:

在这里插入图片描述

按不同FilterType进行过滤

a) 按照注解类型扫描:
在这里插入图片描述
b) 按照可赋值类型进行过滤:(所有CarService类型的Bean都会被扫描)
在这里插入图片描述
c) 使用正则表达式:略

d) 使用自定义方式:

在这里插入图片描述
实现TypeFilter接口

package com.EzerbelCN.config;
import java.io.IOException;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;

public class MyTypeFilter implements TypeFilter {
	/**
	 *@param metadataReader : 读取到的当前正在扫描类的信息
	 *@param metadataReaderFactory:  a factory for obtaining metadata readers for other classes (such as super classes and interfaces)
	 *  
	 */
	public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
			throws IOException {
		//获得当前类的注解信息
		AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
		//获得当前正在扫描类的信息
		ClassMetadata classMetadata = metadataReader.getClassMetadata();
		//获得当前类资源(类的路径)
		Resource resource = metadataReader.getResource();
		String className = classMetadata.getClassName();
		System.out.println("MyTypeFilter 正在 match ------> " + className);
		
		if(className.contains("car")) {return true;}
		return false;	
	}
}

设置组件的作用域

Bean默认是单实例的,使用@Scope进行相关配置

在这里插入图片描述

测试一下,单实例和多实例分别是在何时创建组件?

在这里插入图片描述结果:

在这里插入图片描述

懒加载

经过前面测试,可以发现实例模式下,默认是在容器启动时创建实例,可以使用@Lazy懒加载,使之在第一次获取时再创建和初始化。

使用@Conditional按条件注册

0.可以放在方法头部或者类的头部,无论哪个位置都要实现Condition接口:

package com.EzerbelCN.condition;

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class LinuxCondition implements Condition {
	/**
	 *  context 判断条件能使用的上下文环境
	 *  metadata 注释信息
	 */
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		//获取ioc使用的beanfactory
		ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
		ClassLoader classLoader = context.getClassLoader();
		//获取bean定义的注册类
		BeanDefinitionRegistry registry = context.getRegistry();
		//获取操作系统名
		Environment environment = context.getEnvironment();
		String osname = environment.getProperty("os.name");
		if(osname.toLowerCase().contains("linux")) {return true;}
		return false;
	}
}
  • 1.放在方法的头部,表示只有满足条件时,对应的组件才会被注册:

在这里插入图片描述

  • 2.放在类的头部,表示只有满足条件时,内部的方法对应的组件才可能被注册:

在这里插入图片描述

利用@Import等注册组件

给容器中注册组件的方式:

  1. 包扫描+组件标注(@Controller/@Service/@Repository/@Component)
  2. @Bean (可以导入第三方包里面的组件)
  3. @Import 快速给容器中导入组件
  4. 使用Spring提供的FactoryBean

导入方式注册
a. 使用@Import(组件.class)标注在配置类,自动导入,默认id为全类名

@Import({Doggy.class,Piggy.class})

b.在@import中使用ImportSelector接口

首先要实现该接口
在这里插入图片描述

@Import({Doggy.class,Piggy.class,CustomImportSelector.class})

c.在@import中使用ImportBeanDefinitionRegistrar接口

实现接口
在这里插入图片描述

@Import({Doggy.class,Piggy.class,CustomImportSelector.class,CustomImportBeanDefinitionRegistrar.class})

d.使用FactoryBean 接口:

在这里插入图片描述

  • 注册类中配置

在这里插入图片描述
使用该方法注册的Bean实际上为FactoryBean中getObject返回的实例
如何获得FactoryBean本身呢?使用&作为前缀,再从 ioc 中getBean

@Test
	public void test08() {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
		Object bean1 = context.getBean("letterFactoryBean");
		System.out.println(bean1.getClass());
		
		Object bean2 = context.getBean("&letterFactoryBean");
		System.out.println(bean2.getClass());
	}
  • 测试结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值