springboot学习:组件注册

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/lw305993897/article/details/102676801

1、@Configuration和@Bean注册

@Configuration:使当前类成为一个配置类;
@Bean:给容器注册一个实例,类型为返回值的类型,id默认是用方法名作为id;

  • pom.xml引用:
<dependency>
	    <groupId>org.springframework</groupId>
	    <artifactId>spring-context</artifactId>
	    <version>4.3.12.RELEASE</version>
	</dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  • MainConfig类:
@Configuration
public class MainConfig {
	@Bean
	public Bean1 bean1() {
		return new Bean1();
	}
}
  • Bean1类:
public class Bean1 {

}
  • Test1类:
public class Test1 {
	@SuppressWarnings("resource")
	@Test
	public void test1() {
		// 获取spring上下文
		ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
		Bean1 b = context.getBean(Bean1.class);
		System.out.println(b);// 输出:sprint_test1.dav.bean.Bean1@628016f7
	}
}

2、@ComponentScans注册

@ComponentScan value:指定扫描的包路径;

  • MainConfig类:
@Configuration
@ComponentScan(value = "com.dav")
public class MainConfig {
}

  • Service类
@org.springframework.stereotype.Service
public class Service {
}
  • Test1类:
@Test
public void test1() {
	ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
	System.out.println(context.getBean(com.dav.service.Service.class));// com.dav.service.Service@1df41e93
}

3、自定义TypeFilter指定过滤规则

excludeFilters = Filter[] :指定扫描的时候按照指定规则排除组件
includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件
FilterType.ANNOTATION:按照注解
FilterType.ASSIGNABLE_TYPE:按照指定类型
FilterType.REGEX:使用正则表达式
FilterType.CUSTOM:使用正则表达式
useDefaultFilters:true(使用默认的过滤器),false(使用自定义的过滤器)

  • MainConfig类:
@Configuration
@ComponentScans(value = {@ComponentScan( value = "com.dav", includeFilters = {
		@Filter(type = FilterType.CUSTOM , classes = MyTypeFilter.class)
},useDefaultFilters = false)})
public class MainConfig {

}
  • MyTypeFilter类:
public class MyTypeFilter implements TypeFilter{
	/**
	 * metadataReader:读取到的当前正在扫描的类信息
	 * metadataReaderFactory:可以获取其他类信息
	 */
	public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
			throws IOException {
		// 获取当前类注解信息
		AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
		// 获取当前正在扫描类的类信息
		ClassMetadata classMetadata = metadataReader.getClassMetadata();
		// 获取当前类资源(类路径)
		Resource resource = metadataReader.getResource();
		String className = classMetadata.getClassName();
		if(className.contains("er")) {
			System.out.println("className--" + className);
			// 输出:
//			className--com.dav.config.MyTypeFilter
//			className--com.dav.service.Service
			return true;
		}
		return false;
	}
}
  • Dao类:
@Repository
public class Dao {

}
  • Test1类:
@Test
public void test1() {
	ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
	System.out.println("----" + context.getBean(Dao.class));// 没有输出
}

4、@Scope和@Lazy

调整作用域
singleton:单实例(默认)>ioc容器启动会调用方法创建对象放到ioc容器,后续获取是从容器拿;
prototype:多实例>ioc容器启动不会调用方法创建对象,后续获取才会调用方法创建对象;
request:同一次请求创建一个实例;
session:同一个会话创建一个实例;
懒加载:
@Lazy
单实例bean:默认在容器启动的时候创建对象;
懒加载:容器启动不创建对象.第一次使用时创建对象,并初始化;

  • MainConfig类:
@Configuration
@ComponentScans(value = {@ComponentScan( value = "com.dav", includeFilters = {
		@Filter(type = FilterType.CUSTOM , classes = MyTypeFilter.class)
},useDefaultFilters = false)})
public class MainConfig {

	@Bean
	@Scope(value = "prototype")
	@Lazy
	public Bean1 bean1() {
		System.out.println("getBean....");
		return new Bean1();
	}
}
  • Test1类:
@Test
public void test1() {
	ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
	System.out.println("获取spring上下文");
	Bean1 a = context.getBean(Bean1.class);
	Bean1 b = context.getBean(Bean1.class);
	System.out.println(a == b);
}

在这里插入图片描述

  • 在初始化容器的时候并没有创建实例,而是在调用的时候创建

5、@Conditional按照条件注册

满足当前条件,这个类中配置的所有实例注册才能生效

  • SystemCondition类:

如果当前系统是linux系统则注册实例

public class SystemCondition implements Condition {
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		// 1、获取到ioc使用的bean工厂
		ConfigurableBeanFactory factory = context.getBeanFactory();
		// 2、获取类加载器
		context.getClassLoader();
		// 3、获取运行环境
		Environment environment = context.getEnvironment();
		// 4、获取bean定义的注册类
		context.getRegistry();
		String property = environment.getProperty("os.name");
		if(property.contains("linux")) {
			return true;
		}
		return false;
	}
}
  • MainConfig类:
@Conditional({SystemCondition.class})
@Configuration
public class MainConfig {
	@Bean
	public Bean1 bean1() {
		System.out.println("getBean....");
		return new Bean1();
	}
}
  • Test1类:
@Test
public void test1() {
	ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
	System.out.println("获取spring上下文");
	Bean1 a = context.getBean(Bean1.class);
	System.out.println(a);// 没有输出
}

6、@Import导入一个实例

1.@Import({类.class})
2.ImportSelector: 返回需要导入的组件的全类名数组;
3.ImportBeanDefinitionRegistrar:手动注册bean到容器中;

  • Bean2类:
public class Bean2 {
}
  • Bean3类:
public class Bean3 {
}
  • Bean4类:
    public class Bean4 {
    }
  • MyImportSelect类:
public class MyImportSelect implements ImportSelector {

	/**
	 * AnnotationMetadata:当前标注@Import注解的类的所有注解信息
	 */
	public String[] selectImports(AnnotationMetadata importingClassMetadata) {
		// 不要返回null,会报空指针异常
		return new String[] {"com.dav.bean.Bean1","com.dav.bean.Bean2"};
	}
}
  • MainConfig类:
@Configuration
@Import({MyImportSelect.class,Bean3.class,MyImportBeanDefinitionRegister.class})
public class MainConfig {
}
  • MyImportBeanDefinitionRegister类:
public class MyImportBeanDefinitionRegister implements ImportBeanDefinitionRegistrar{
	/**
	 * AnnotationMetadata:当前类注解信息
	 * BeanDefinitionRegistry:BeanDefinition注册类
	 */
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		// 是否包含某个bean
		boolean tmp = registry.containsBeanDefinition("com.dav.bean.Bean4");
		if(!tmp) {
			// 指定bean的注册信息
			RootBeanDefinition beanDefinition = new RootBeanDefinition(Bean4.class);
			// 注册bean
			registry.registerBeanDefinition("bean4", beanDefinition);;
		}
	}
}
  • Test1类:
@Test
public void test1() {
	ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
	System.out.println("获取spring上下文");
	Bean1 a = context.getBean(Bean1.class);
	Bean2 b = context.getBean(Bean2.class);
	Bean3 c = context.getBean(Bean3.class);
	Bean4 d = context.getBean(Bean4.class);
	System.out.println(a + "-" + b + "-" + c + "-" + d);
	// 输出:
	// [email protected]@[email protected]@20de643a
}

7、使用FactoryBean注册

使用Spring提供的FactoryBean;
1.默认获取的是工厂bean调用getObject创建的对象;
2.要获取工厂bean本身,需要在id前面&符号(&colorFactoryBean)

  • Bean1FacotryBean类:
//创建一个Spring定义的FactoryBean
public class Bean1FacotryBean implements FactoryBean<Bean1> {
	// 返回一个Bean1对象
	public Bean1 getObject() throws Exception {
		return new Bean1();
	}
	public Class<?> getObjectType() {
		return Bean1.class;
	}
	// 控制是否单例(true:单例,false:多实例)
	public boolean isSingleton() {
		return true;
	}
}
  • MainConfig类
@Configuration
public class MainConfig {
	@Bean
	public Bean1FacotryBean bean1FacotryBean() {
		return new Bean1FacotryBean();
	}
}
  • Test1类:
@Test
public void test1() {
	ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
	Object object = context.getBean("bean1FacotryBean");
	System.out.println("bean类型:"+object.getClass());// bean类型:class com.dav.bean.Bean1
	object = context.getBean("&bean1FacotryBean");
	System.out.println("bean类型:"+object.getClass());// bean类型:class com.dav.condition.Bean1FacotryBean
}

猜你喜欢

转载自blog.csdn.net/lw305993897/article/details/102676801
今日推荐