Spring注解版之组件注册

1 通过@Configuration和@Bean为容器添加Bean
Spring使用@configuration注解标识配置类
@Bean注解
向容器中注册Bean,id为方法名,同时也可以使用@Bean(“person”)的方式配置方法名
使用AnnotationConfigApplicationContext可以获取容器,容器中注册的bean通过注解方式配置进去,AnnotationConfigApplicationContext的构造方法需要指定配置类的class类型,具体代码为

ApplicationContext applicatioinContext = new AnnotationConfigApplicationContext(MainConfig.class); 

applicatioinContext .getBean(Person.class) 获取bean
applicatioinContext .getBeanNamesForType(Person.class)
通过Class类型获取bean的名字 返回结果为String[]

2 通过@ComponentScan完成包扫描
依旧写在有@Configuration注解的配置文件中,通过注解参数指定要扫描的包,具体示例如下:

@Configuraion
@ComponentScan(value = " com.meituan", includeFilters = {
    @Filter(type = FilterType.ANNOTATION,classes = {Controller.class,Service.Class}),
    @Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {BookService.class }),
},useDefaultFilters = false)
@ComponentScan(value = " com.meituan", excludeFilters = {
    @Filter(type = FilterType.ANNOTATION,classes = {Controller.class,Service.Class})
})
public Class MainConfig{
}

excludeFilters = Filter[] 扫描的时候按照规则排除哪些组件
includeFilters = Filter[] 扫描的时候按照规则只包含哪些组件,但是需要将useDefaultFilters设置为false后才能生效
applicatioinContext .getBeanDefinitionNames() 能够看到bean容器中所有容器定义的名字,返回结果为String[]
在JDK1.8以后ComponentScan注解可以重复使用,同时也可以通过@ComponentScans注解指定多个扫描
3 通过TypeFilter指定过滤规则
FilterType.ANNOTATION 按照注解进行过滤
FilterType.ASSIGNABLE_TYPE 按照指定的类型进行过滤
FilterType.ASPECTJ 使用ASPECTJ表达式
FilterType.REGEX 使用正则表达式
FilterType.CUSTOM 使用自定义规则
自定义规则必须是一个TypeFilter的实现类

public class MyTypeFilter implements TypeFilter {

	@Override
	public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
			throws IOException {
		// TODO Auto-generated method stub
		//获取当前类注解的信息
		AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
		// 获取当前正在扫描的类的类信息
		ClassMetadata classMetadata = metadataReader.getClassMetadata();
		// 获取当前类资源(类的路径)
		Resource resource = metadataReader.getResource();
	
		String className = classMetadata.getClassName();
		System.out.println("--->"+className);
		if(className.contains("er")){
			return true;
		}
		return false;
	}
}

4 通过Scope注解调整组件作用域
@Scope
prototype:多例的 ioc容器启动并不会去调用方法创建对象在容器中,而是每次获取时才会调用方法创建对象,获取几次调用几次
singleton:单例的(默认值) ioc容器启动会调用方法创建对象放到ioc容器中,以后每次获取就是从容器中拿
针对单实例bean,通过@lazy注解可以将其调整为懒加载方式

5 通过Conditional注解完成条件注册
可以通过Conditional注解完成条件注册
@Conditional(LinuxCondition.Class) 必须满足条件才能将bean注册进容器中,该注解既可以修饰类,也可以修饰方法。
最终的判断类需要实现Condition注解

public class LinuxCondition implements Condition {

	/**
	 * ConditionContext,判断条件能使用的上下文环境
	 * AnnotatedTypeMetadata注释信息
	 */
	@Override
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		//1,能获取到ioc使用的beanfactory
		ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
		//2获取类加载器
		ClassLoader classLoader = context.getClassLoader();
		//3获取当前环境
		Environment environment = context.getEnvironment();
		//4获取到bean定义的注册类
		BeanDefinitionRegistry registry = context.getRegistry();
		String property = environment.getProperty("os.name");
		//可以判断容器中bean的注册情况,也可以给容器中注册bean
		boolean definition = registry.containsBeanDefinition("person");
		if(property.contains("linux")){
			return true;
		}
		return false;
	}
}

给容器中中注册组件的几种方式
包扫描+组件标注注解(@Component、@Service、@Controller、@Repository,添加到自己写的类上边)
2、@Bean[导入的第三方包里面的组件]
3、@Import[快速给容器中导入一个组件]
@Import({Color.class,Red.class})也能通过数组的方式导入多个组件
1、Import(类名),容器中就会自动注册这个组件,id默认是组件的全名
2、ImportSelector:返回需要导入的组件的全类名的数组
@Import(Color.class, Red.class, MyImportSelector.class)

//自定义逻辑返回需要导入的组件
public class MyImportSelector implements ImportSelector {
	//返回值就是导入到容器中组件的全类名
	//AnnotationMetadata:当前标注@Import注解的类的所有注解信息
	@Override
	public String[] selectImports(AnnotationMetadata importingClassMetadata) {
		// TODO Auto-generated method stub
		//importingClassMetadata
		//方法不要返回null值
		return new String[]{"com.atguigu.bean.Blue","com.atguigu.bean.Yellow"};
	}
}

通过ImportSelector的实现类,将该类型的返回值导入到容器中
3、ImportBeanDefinitionRegistrar:手动注册bean
@Import(Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class)

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
	/**
	 * AnnotationMetadata当前类的注解信息
	 * BeanDefinitionRegistry:BeanDefinition注册类
	 * 		把所有添加到容器中的bean调用
	 * 		BeanDefinitionRegistry.registerBeanDefinition手工注册进来
	 */
	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		
		boolean definition = registry.containsBeanDefinition("com.atguigu.bean.Red");
		boolean definition2 = registry.containsBeanDefinition("com.atguigu.bean.Blue");
		if(definition && definition2){
			//指定Bean定义信息,(Bean的类型)
			RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);
			//注册一个bean,指定bean名
			registry.registerBeanDefinition("rainBow", beanDefinition);
		}
	}
}

4、使用Spring提供的FactoryBean(工厂bean)
1、默认获取到的是工厂bean调用getObject创建的对象

//创建一个Spring定义的FactoryBean
public class ColorFactoryBean implements FactoryBean<Color> {
	//返回一个Color对象,这个对象会添加到容器中
	@Override
	public Color getObject() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("ColorFactoryBean...getObject...");
		return new Color();
	}
	@Override
	public Class<?> getObjectType() {
		// TODO Auto-generated method stub
		return Color.class;
	}
	//是否是单例
	//true,这个bean是一个单实例bean,在容器中保存一份
	//false,这个bean多实例,每次获取都会创建一个新的bean
	@Override
	public boolean isSingleton() {
		// TODO Auto-generated method stub
		return false;
	}
}

最后在config类中注入此FactoryBean

@Bean
	public ColorFactoryBean colorFactoryBean(){
		return new ColorFactoryBean();
	}

这里我们貌似向容器中注入的是FactoryBean,但是实际上容器中注入bean的类型是我们在FactoryBean中所生成的类型

Object bean2 = applicationContext.getBean("colorFactoryBean");

如果想要获取到bean本身,需要给id前面加个&标识

Object bean4 = applicationContext.getBean("&colorFactoryBean");
System.out.println(bean4.getClass());
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值