【spring系列】之2:@Conditional按照条件注册bean

给容器注册bean的几种方式:

1.包扫描:ComponentScan+bean注解(@Controller,@Service,@Repository,@Component,Bean):

2.条件注入:@Conditional按条件选择注入

3.@Import快速给容器中导入一个组件

4.FactoryBean注册

@Conditional是基于条件注册bean的注解,也是springboot的实现原理。

当满足配置选择条件时,便会注册bean到容器中。

@Condotional注解源码如下:

扫描二维码关注公众号,回复: 3421469 查看本文章
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {

	/**
	 * All {@link Condition}s that must {@linkplain Condition#matches match}
	 * in order for the component to be registered.
	 */
	Class<? extends Condition>[] value();

}

value 为实现Condition接口的实现类。由此我们可以猜测,@Condotional的实现就是根据value中的逻辑来判断是否需要加载bean的。

下面,我们写一个关于@Condotional按条件注册bean的例子。

首先定义两个实现Condition的接口实现类:LinuxConditional和WindowConditional

public class WindowConditional implements Condition {

	@Override
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		// TODO是否linux系统
		// 1、能获取到ioc使用的beanfactory
		ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
		System.out.println(beanFactory.getSingletonCount());
		// 2、获取类加载器
		ClassLoader classLoader = context.getClassLoader();
		System.out.println(classLoader.toString());
		// 3、获取当前环境信息
		Environment environment = context.getEnvironment();
		// 4、获取到bean定义的注册类
		BeanDefinitionRegistry registry = context.getRegistry();

		String property = environment.getProperty("os.name");

		// 可以判断容器中的bean注册情况,也可以给容器中注册bean
		boolean definition = registry.containsBeanDefinition("person");
		System.out.println(definition);
		if (property.toUpperCase().contains("window".toUpperCase())) {
			return true;
		}

		return false;
	}

}
public class LinuxConditional implements Condition {

	@Override
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		// TODO是否linux系统
		// 1、能获取到ioc使用的beanfactory
		ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
		System.out.println(beanFactory.getSingletonCount());
		// 2、获取类加载器
		ClassLoader classLoader = context.getClassLoader();
		System.out.println(classLoader.toString());
		// 3、获取当前环境信息
		Environment environment = context.getEnvironment();
		// 4、获取到bean定义的注册类
		BeanDefinitionRegistry registry = context.getRegistry();

		String property = environment.getProperty("os.name");

		// 可以判断容器中的bean注册情况,也可以给容器中注册bean
		boolean definition = registry.containsBeanDefinition("person");
		System.out.println(definition);
		if (property.toUpperCase().contains("linux".toUpperCase())) {
			return true;
		}

		return false;
	}

}

两个条件注入类实现好了,接着,写我们的配置类:ConditionalConfig

@Configuration
public class ConditionalConfig {

	@Conditional({ WindowConditional.class })
	@Bean
	public Person person() {
		System.out.println("给容器中添加Person....");
		return new Person("张三", 25);
	}

}

最后,我们来做一个测试:

	@Test
	public void testPerson() {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConditionalConfig.class);
		printBeans(context);
		System.out.println("--------------------");
		Person p = context.getBean(Person.class);
		Person p2 = context.getBean(Person.class);
		System.out.println(p == p2);
		System.out.println(p);
	}

	private void printBeans(ApplicationContext context) {

		String[] defBeans = context.getBeanDefinitionNames();
		for (String name : defBeans) {
			System.out.println(name);
		}

	}

以下为打印的内容:

现在,我们将注解注入条件更换为:@Conditional({ LinuxConditional.class })

查看打印结果:

可以发现,Person并没有注册进来。

总结:

1.条件选择器需要实现Condition接口

2.在配置中条件@Conditional注解并设置value为条件选择器 

需要注意的是:@Conditional既可以配置在类上也可以配置在方法上。

1.当配置在类上时,类中组件统一设置。满足当前条件,这个类中配置的所有bean注册才能生效;

2.当配置在方法上时,只对当前方法生效。

猜你喜欢

转载自blog.csdn.net/licwzy/article/details/82835681
今日推荐