背景:
本文主要记录代码方式进行组件注册,以及一些进阶玩法。
Spring注册组件的方法:
1.@ComponentScan
- 最常用的就是组件扫描配合配合@Component、@Controller、@Service、@Configuration、@Repository;
- value指定扫面的包
- excludeFilter= excludeFilters = @ComponentScan.Filter(classes = Controller.class)排除Controller注解的组件,当然也可以自定义注解;
- excludeFilter=excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, class = UserController.class), 可以排除指定类;
- excludeFilter=excludeFilters=@ComponentScan.Filter(type = CUSTOM, class=MyTypeFilter.class), 然后自定义一个类实现TypeFilter接口, 重写方法, 即可按照既定的逻辑决定是否加载bean;
2.@Bean
- 此注解常用于注册第三方包中的类。注册的bean的id默认为方法名,我们可以用@Bean("person")改变id。
import com.atguigu.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class BeanConfig {
@Bean
public Person person() {
return new Person();
}
}
- @Bean也可以配合@Conditional注解使用,达到选择性加载Bean的目的 。注解中需要传入一个Condition接口的自定义实现类,在重写方法中我们可以实现自己想要的逻辑。
import com.atguigu.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
@Configuration
public class BeanConfig {
@Bean
@Conditional(value = {MyCondition.class})
public Person person() {
return new Person();
}
}
3.@Import
- 直接注册一个类,只需要在@Import注解中传入这个类的class
import com.atguigu.bean.Person;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import(value = {Person.class})
public class BeanConfig {
}
- 传入ImportSelector的实现类,可以注册一组Bean,其中ImportSelector接口的方法为返回一个String[ ], 数组元素为类的全路径名;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import(value = MyImportSelector.class)
public class BeanConfig {
}
- 传入ImportBeanDefinition接口的实现类,可以在重写方法中手动注册bean;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
import java.util.Arrays;
import java.util.Set;
public class MyBeanRegistry implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
// AnnotationMetadata 可以获取所有的注解
Set<String> annotationTypes = metadata.getAnnotationTypes();
annotationTypes.forEach(System.out::println);
// BeanDefinitionRegistry可以获取所有注册的bean
String[] beanDefinitionNames = registry.getBeanDefinitionNames();
Arrays.stream(beanDefinitionNames).forEach(System.out::println);
// 注册bean
registry.registerBeanDefinition("blue", new RootBeanDefinition(Blue.class));
}
}
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import(value = MyBeanRegistry.class)
public class BeanConfig {
}
4.使用Spring提供的FactoryBean手动注册bean
import org.springframework.beans.factory.FactoryBean;
/**
* FileName: MyFactoryBean
* DESCRIPTION:
*
* @author: SLY
* @create: 2019/4/6
*/
public class MyFactoryBean implements FactoryBean<Color> {
@Override
public Color getObject() throws Exception {
return new Color();
}
@Override
public Class<?> getObjectType() {
return Color.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class BeanConfig {
// 特别注意的是,这里看似注册的是MyFactoryBean,但是获取到的却是Color对象。
// 如果希望获取MyFactoryBean本身,可以使用applicationContext.getBean("&myFactoryBean")
// 通过加一个&前缀, 就可以获取到工厂bean本身
@Bean
public MyFactoryBean myFactoryBean() {
return new MyFactoryBean();
}
}