意义
按照一定的条件进行判断,满足条件给容器中注册bean
定义信息
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Indicates that a component is only eligible for registration when all
* {@linkplain #value specified conditions} match.
*
* <p>A <em>condition</em> is any state that can be determined programmatically
* before the bean definition is due to be registered (see {@link Condition} for details).
*
* <p>The {@code @Conditional} annotation may be used in any of the following ways:
* <ul>
* <li>as a type-level annotation on any class directly or indirectly annotated with
* {@code @Component}, including {@link Configuration @Configuration} classes</li>
* <li>as a meta-annotation, for the purpose of composing custom stereotype
* annotations</li>
* <li>as a method-level annotation on any {@link Bean @Bean} method</li>
* </ul>
*
* <p>If a {@code @Configuration} class is marked with {@code @Conditional},
* all of the {@code @Bean} methods, {@link Import @Import} annotations, and
* {@link ComponentScan @ComponentScan} annotations associated with that
* class will be subject to the conditions.
*
* <p><strong>NOTE</strong>: Inheritance of {@code @Conditional} annotations
* is not supported; any conditions from superclasses or from overridden
* methods will not be considered. In order to enforce these semantics,
* {@code @Conditional} itself is not declared as
* {@link java.lang.annotation.Inherited @Inherited}; furthermore, any
* custom <em>composed annotation</em> that is meta-annotated with
* {@code @Conditional} must not be declared as {@code @Inherited}.
*
* @author Phillip Webb
* @author Sam Brannen
* @since 4.0
* @see Condition
*/
@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();
}
定义信息显示可以注解在方法上或者类上
属性有一个Class数组,范型为Condition实现类(点进去是个接口)
Condition类定义信息
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
* A single {@code condition} that must be {@linkplain #matches matched} in order
* for a component to be registered.
*
* <p>Conditions are checked immediately before the bean-definition is due to be
* registered and are free to veto registration based on any criteria that can
* be determined at that point.
*
* <p>Conditions must follow the same restrictions as {@link BeanFactoryPostProcessor}
* and take care to never interact with bean instances. For more fine-grained control
* of conditions that interact with {@code @Configuration} beans consider the
* {@link ConfigurationCondition} interface.
*
* @author Phillip Webb
* @since 4.0
* @see ConfigurationCondition
* @see Conditional
* @see ConditionContext
*/
public interface Condition {
/**
* Determine if the condition matches.
* @param context the condition context
* @param metadata metadata of the {@link org.springframework.core.type.AnnotationMetadata class}
* or {@link org.springframework.core.type.MethodMetadata method} being checked.
* @return {@code true} if the condition matches and the component can be registered
* or {@code false} to veto registration.
*/
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
是个接口,只有一个matches方法,返回true时会注册相应的bean
Condition子类编写
package com.ouyangxizhu.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.io.ResourceLoader;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class MacCondition implements Condition {
/**
*
* @param context 判断条件能使用的上下文(环境)
* @param metadata 注解信息
* @return
*/
@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();
//5. 获取ResourceLoader
ResourceLoader resourceLoader = context.getResourceLoader();
String property = environment.getProperty("os.name");
//可以判断容器中的bean注册情况,也可以给容器中注册bean
boolean definition = registry.containsBeanDefinition("person");
System.out.println("========environment.getProperty(\"os.name\")============");
System.out.println(property);
if(property.contains("Mac")){
return true;
}
return false;
}
}
配置类
package com.ouyangxizhu.config;
import com.ouyangxizhu.bean.Person;
import com.ouyangxizhu.condition.MacCondition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MainConfigCondition {
@Bean
@Conditional({MacCondition.class})
public Person mac(){
return new Person("mac", 48);
}
@Bean
public Person bill(){
return new Person("bill", 68);
}
}
启动类
package com.ouyangxizhu;
import com.ouyangxizhu.bean.Person;
import com.ouyangxizhu.config.MainConfigCondition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.Map;
public class MainTestCondition {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfigCondition.class);
String[] beanDefinitionNames = context.getBeanDefinitionNames();
System.out.println("=========context.getBeanDefinitionNames()=========");
for (String name : beanDefinitionNames) {
System.out.println(name);
}
Map<String, Person> beans = context.getBeansOfType(Person.class);
System.out.println("=========context.getBeansOfType(Person.class)========");
for (Map.Entry entry : beans.entrySet()) {
System.out.println("key:" + entry.getKey() + ", value:" + entry.getValue());
}
}
}
运行结果
八月 03, 2020 10:29:23 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@31cefde0: startup date [Mon Aug 03 22:29:23 CST 2020]; root of context hierarchy
========environment.getProperty("os.name")============
Mac OS X
=========context.getBeanDefinitionNames()=========
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfigCondition
mac
bill
=========context.getBeansOfType(Person.class)========
key:mac, value:Person{name='mac', age=48}
key:bill, value:Person{name='bill', age=68}
@Condition在配置类上
package com.ouyangxizhu.config;
import com.ouyangxizhu.bean.Person;
import com.ouyangxizhu.condition.MacCondition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
//类中组件统一设置。满足当前条件,这个类中配置的所有bean注册才能生效;
@Conditional({MacCondition.class})
@Configuration
public class MainConfigCondition {
@Bean
@Conditional({MacCondition.class})
public Person mac(){
return new Person("mac", 48);
}
@Bean
public Person bill(){
return new Person("bill", 68);
}
}