前提
SSM框架,使用的是ClassPathXmlApplicationContext(IOC容器),一个加载配置文件
spring Boot框架,启动加载的是AnnotationConfigApplicationContext(IOC容器),一个扫描注解
@ComponentScan
扫描bean,SpringBootApplication里面有这个注解
jdk1.8,可以多次使用@ComponentScan,jdk1.8之前,可以使用@ComponentScans,里面写多个@ComponentScan
@ComponentScan( value = {"com.xuecheng.api"}, //排除Controller注解的类 excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})}, //includeFilters要和useDefaultFilters搭配,禁用默认filter includeFilters ={@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})}, useDefaultFilters = false )
- FilterType.ASSIGNABLE_TYPE:给定类型,即使没有注解也可以加载到容器中,并且这个类的子类也会加载
- FilterType.Custom:自定义规则,参数是给一个自定义的TypeFilter的实现类,如下
class TestFilter implements TypeFilter { /** * @param metadataReader:当前正在扫描的类的信息 * @param metadataReaderFactory:可以获取到其他任何类的信息 * @return * @throws IOException */ @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { //获取当前类注解信息 AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); //获取当前类的信息 ClassMetadata classMetadata = metadataReader.getClassMetadata(); if (classMetadata.getClassName()==""){ return true; } return false; } } @ComponentScan( value = {"com.xuecheng.api"}, //includeFilters要和useDefaultFilters搭配,禁用默认filter includeFilters ={@ComponentScan.Filter(type = FilterType.CUSTOM,classes = {TestFilter.class})}, useDefaultFilters = false )
@Scope
@Configuration class Config{ /** * ConfigurableBeanFactory#SCOPE_PROTOTYPE * * @see ConfigurableBeanFactory#SCOPE_SINGLETON * 这两个一般不用,实际中,直接手动new对象,放到请求域中 * * @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST * * @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION * */ @Scope("PROTOTYPE") @Bean public User user(){ } }
@Lazy
@Configuration class Config{ //只有单实例,才可以使用 @Lazy @Bean public User user(){ } }
@Conditional
class testCondition implements Condition{ @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { context.getBeanFactory(); context.getClassLoader(); context.getRegistry(); context.getResourceLoader(); String str = context.getEnvironment().getProperty("os.name"); if ("Windows".contains(str)){ return true; } return false; } } //必须满足这个条件,类中所有的bean,才能生效 @Conditional({testCondition.class}) @Configuration class Config{ //必须满足这个条件,当前bean,才能生效 @Conditional({testCondition.class}) @Bean public User user(){ } }
@Import
常规的导入bean方式:
- ComponentScan+@component
- @Configuration+@Bean
- @Import【@Import,@ImportSelector,@ImportBeanDefinitionRegistrar】
- spring提供的FactoryBean(工厂Bean)
使用方式1
导入常规类
/** * * {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar} * * or regular component classes to import (或者导入常规的类,组件名:全限定类名) */ @Import({User.class}) @Configuration class Config{ }
使用方式2
导入@ImportSelector
/** * 自定义逻辑需要导入的组件 */ class ImportSelectorTest implements ImportSelector{ /** * * @param importingClassMetadata:当前标注@Import注解的类的 所有的注解 * @return */ @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { //可以获取除了当前标注@Import注解的类的 其他所有的注解 //importingClassMetadata importingClassMetadata.getAnnotationTypes(); //需要返回需要导入组件的全类名数组 return new String[]{"com.zy.User"}; } } @Import({ImportSelectorTest.class}) @Configuration class Config{ }
使用方式3
class ImportBeanDefinitionRegistrarTest implements ImportBeanDefinitionRegistrar{ @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(User.class); registry.registerBeanDefinition("user",rootBeanDefinition); } } @Import({ImportBeanDefinitionRegistrarTest.class}) @Configuration class Config{ }
FactoryBean
class FactoryBeanTest implements FactoryBean{ //返回要给对象,这个对象会添加到容器中 @Override public Object getObject() throws Exception { User user = new User(); return user; } @Override public Class<?> getObjectType() { return User.class; } @Override public boolean isSingleton() { return true; } } @Configuration class Config{ @Bean public FactoryBeanTest factoryBeanTest(){ //FactoryBean return new FactoryBeanTest(); } public static void main(){ //当容器获取bean的时候,获取的是FactoryBeanTest.getObject()返回的对象 Object b = applicationContext.getBean("FactoryBeanTest"); //此时获取的是FactoryBeanTest本身了 //BeanFactory.FACTORY_BEAN_PREFIX=& Object b = applicationContext.getBean("&FactoryBeanTest"); } }