您的位置:首页技术文章
文章详情页

Spring容器注册组件实现过程解析

【字号: 日期:2023-09-13 18:51:10浏览:6作者:猪猪

1、@Configuration&@Bean给容器中注册组件

@Configuration及@Bean的使用参考如下代码:

package com.atguigu.config; import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.FilterType;import org.springframework.context.annotation.ComponentScan.Filter;import org.springframework.context.annotation.ComponentScans; import com.atguigu.bean.Person; //配置类==配置文件@Configuration //告诉Spring这是一个配置类 @ComponentScans( value = {@ComponentScan(value='com.atguigu',includeFilters = {/* @Filter(type=FilterType.ANNOTATION,classes={Controller.class}), @Filter(type=FilterType.ASSIGNABLE_TYPE,classes={BookService.class}),*/ @Filter(type=FilterType.CUSTOM,classes={MyTypeFilter.class})},useDefaultFilters = false) } )//@ComponentScan value:指定要扫描的包//excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件//includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件//FilterType.ANNOTATION:按照注解//FilterType.ASSIGNABLE_TYPE:按照给定的类型;//FilterType.ASPECTJ:使用ASPECTJ表达式//FilterType.REGEX:使用正则指定//FilterType.CUSTOM:使用自定义规则public class MainConfig { //给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id @Bean('person') public Person person01(){ return new Person('lisi', 20); } }

2、@ComponentScan-自动扫描组件&指定扫描规则

@CompoentScan的使用,参考1中以上代码即可。

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

参考如下代码:

package com.atguigu.config; import java.io.IOException; import org.springframework.core.io.Resource;import org.springframework.core.type.AnnotationMetadata;import org.springframework.core.type.ClassMetadata;import org.springframework.core.type.classreading.MetadataReader;import org.springframework.core.type.classreading.MetadataReaderFactory;import org.springframework.core.type.filter.TypeFilter; public class MyTypeFilter implements TypeFilter { /** * metadataReader:读取到的当前正在扫描的类的信息 * metadataReaderFactory:可以获取到其他任何类信息的 */ @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { // TODO Auto-generated method stub //获取当前类注解的信息 AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); //获取当前正在扫描的类的类信息 ClassMetadata classMetadata = metadataReader.getClassMetadata(); //获取当前类资源(类的路径) Resource resource = metadataReader.getResource(); String className = classMetadata.getClassName(); System.out.println('--->'+className); if(className.contains('er')){ return true; } return false; } }

Spring容器注册组件实现过程解析

4、@Scope-设置组件作用域

参考如下代码:

Spring容器注册组件实现过程解析

Spring容器注册组件实现过程解析

5、@Lazy懒加载

Spring容器注册组件实现过程解析

6、@Conditional-按照条件注册bean

package com.atguigu.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.type.AnnotatedTypeMetadata; //判断是否linux系统public class LinuxCondition implements Condition { /** * ConditionContext:判断条件能使用的上下文(环境) * AnnotatedTypeMetadata:注释信息 */ public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { // TODO是否linux系统 //1、能获取到ioc使用的beanfactory ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); //2、获取类加载器 ClassLoader classLoader = context.getClassLoader(); //3、获取当前环境信息 Environment environment = context.getEnvironment(); //4、获取到bean定义的注册类 BeanDefinitionRegistry registry = context.getRegistry(); String property = environment.getProperty('os.name'); //可以判断容器中的bean注册情况,也可以给容器中注册bean boolean definition = registry.containsBeanDefinition('person'); if(property.contains('linux')){ return true; } return false; } }

7、@Import-给容器中快速导入一个组件

源代码如下:

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Import { /** * {@link Configuration @Configuration}, {@link ImportSelector}, * {@link ImportBeanDefinitionRegistrar}, or regular component classes to import. */ Class<?>[] value(); }

package com.atguigu.config; import org.springframework.beans.factory.config.ConfigurableBeanFactory;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Conditional;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Import;import org.springframework.context.annotation.Lazy;import org.springframework.context.annotation.Scope; import com.atguigu.bean.Blue;import com.atguigu.bean.Color;import com.atguigu.bean.ColorFactoryBean;import com.atguigu.bean.Person;import com.atguigu.bean.Red;import com.atguigu.condition.LinuxCondition;import com.atguigu.condition.MyImportBeanDefinitionRegistrar;import com.atguigu.condition.MyImportSelector;import com.atguigu.condition.WindowsCondition;import com.atguigu.test.IOCTest; //类中组件统一设置。满足当前条件,这个类中配置的所有bean注册才能生效;@Conditional({ WindowsCondition.class })@Configuration@Import({ Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class })// @Import导入组件,id默认是组件的全类名public class MainConfig2 { // 默认是单实例的 /** * ConfigurableBeanFactory#SCOPE_PROTOTYPE * * @see ConfigurableBeanFactory#SCOPE_SINGLETON * @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST * request * @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION * sesssion @return * @Scope:调整作用域 prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。 每次获取的时候才会调用方法创建对象; * singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。 * 以后每次获取就是直接从容器(map.get())中拿, request:同一次请求创建一个实例 * session:同一个session创建一个实例 * * 懒加载: 单实例bean:默认在容器启动的时候创建对象; * 懒加载:容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化; * */ // @Scope('prototype') @Lazy @Bean('person') public Person person() { System.out.println('给容器中添加Person....'); return new Person('张三', 25); } /** * @Conditional({Condition}) : 按照一定的条件进行判断,满足条件给容器中注册bean * * 如果系统是windows,给容器中注册('bill') * 如果是linux系统,给容器中注册('linus') */ @Bean('bill') public Person person01() { return new Person('Bill Gates', 62); } @Conditional(LinuxCondition.class) @Bean('linus') public Person person02() { return new Person('linus', 48); } /** * 给容器中注册组件; * 1)、包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)[自己写的类] * 2)、@Bean[导入的第三方包里面的组件] 3)、@Import[快速给容器中导入一个组件] * 1)、@Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名 * 2)、ImportSelector:返回需要导入的组件的全类名数组; * 3)、ImportBeanDefinitionRegistrar:手动注册bean到容器中 4)、使用Spring提供的 * FactoryBean(工厂Bean); 1)、默认获取到的是工厂bean调用getObject创建的对象 * 2)、要获取工厂Bean本身,我们需要给id前面加一个& &colorFactoryBean */ @Bean public ColorFactoryBean colorFactoryBean() { return new ColorFactoryBean(); } }

8、@Import-使用ImportSelect

8.1 配置如下:

Spring容器注册组件实现过程解析

8.2对应的类需实现ImportSelector接口

package com.atguigu.condition; import org.springframework.context.annotation.ImportSelector;import org.springframework.core.type.AnnotationMetadata; //自定义逻辑返回需要导入的组件public class MyImportSelector implements ImportSelector { //返回值,就是到导入到容器中的组件全类名 //AnnotationMetadata:当前标注@Import注解的类的所有注解信息 public String[] selectImports(AnnotationMetadata importingClassMetadata) { // TODO Auto-generated method stub //importingClassMetadata //方法不要返回null值 return new String[]{'com.atguigu.bean.Blue','com.atguigu.bean.Yellow'}; } }

9、@Import-使用ImportBeanDefinitionRegistrar

9.1配置如下:

Spring容器注册组件实现过程解析

9.2对应的类需实现ImportBeanDefinitionRegistrar接口

package com.atguigu.condition; 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 com.atguigu.bean.RainBow; public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { /** * AnnotationMetadata:当前类的注解信息 * BeanDefinitionRegistry:BeanDefinition注册类; * 把所有需要添加到容器中的bean;调用 * BeanDefinitionRegistry.registerBeanDefinition手工注册进来 */ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { boolean definition = registry.containsBeanDefinition('com.atguigu.bean.Red'); boolean definition2 = registry.containsBeanDefinition('com.atguigu.bean.Blue'); if(definition && definition2){ //指定Bean定义信息;(Bean的类型,Bean。。。) RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class); //注册一个Bean,指定bean名 registry.registerBeanDefinition('rainBow', beanDefinition); } } }

10、使用FactoryBean注册组件

10.1 配置如下:

Spring容器注册组件实现过程解析

10.2对应的类需实现org.springframework.beans.factory.FactoryBean<T>接口

package com.atguigu.bean; import org.springframework.beans.factory.FactoryBean; //创建一个Spring定义的FactoryBeanpublic class ColorFactoryBean implements FactoryBean<Color> { //返回一个Color对象,这个对象会添加到容器中 public Color getObject() throws Exception { // TODO Auto-generated method stub System.out.println('ColorFactoryBean...getObject...'); return new Color(); } public Class<?> getObjectType() { // TODO Auto-generated method stub return Color.class; } //是单例? //true:这个bean是单实例,在容器中保存一份 //false:多实例,每次获取都会创建一个新的bean; public boolean isSingleton() { // TODO Auto-generated method stub return false; } }

11、给容器中注册组件-总结

/*** 给容器中注册组件;* 1)、包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)[自己写的类]* 2)、@Bean[导入的第三方包里面的组件] 3)、@Import[快速给容器中导入一个组件]* 1)、@Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名* 2)、ImportSelector:返回需要导入的组件的全类名数组;* 3)、ImportBeanDefinitionRegistrar:手动注册bean到容器中 4)、使用Spring提供的* FactoryBean(工厂Bean); 1)、默认获取到的是工厂bean调用getObject创建的对象* 2)、要获取工厂Bean本身,我们需要给id前面加一个& &colorFactoryBean*/

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持好吧啦网。

标签: Spring
相关文章: