Spring组件注册

Spring注解驱动开发系列:

  1. Spring 组件注册
  2. Spring Bean的生命周期
  3. Spring属性赋值
  4. Spring自动转配
  5. Spring注解驱动开发之AOP

组件注册

@Configuration

声明这是一个配置类

在配置类中可以使用@Bean修饰方法,将该组件加入容器中。组件类型为返回值类型,组件id为方法名。

@Configuration
public class SpringConfig {
    // 将组件加入容器中,组件类型为People,组件为People("ming",null,null),组件名称默认为为people1,但是@Bean注解中设置了为people
    @Bean("people")
    public People people1(){
        return new People("ming",null,null);
    }
}

@ComponentScan

开启组件扫描,将扫描范围中用@Component、@Repository、@Service、@Comtroller标注的类生成实例加入容器中。

@Repository、@Service、@Comtroller都继承@Component

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {
	/**
	 * The value may indicate a suggestion for a logical component name,
	 * to be turned into a Spring bean in case of an autodetected component.
	 * @return the suggested component name, if any (or empty String otherwise)
	 */
	@AliasFor(annotation = Component.class)	//继承了Component注解,@Service、@Comtroller也一样有这行代码
	String value() default "";
}

@ComponentScan使用

@ComponentScan(
        basePackages = {"south.block"},
        includeFilters ={
            @ComponentScan.Filter(type = FilterType.ANNOTATION,
                    value = { Service.class, Repository.class })
        },
        useDefaultFilters = false,
        excludeFilters = {
           	@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
                    value =  UserService.class )
        }
        )

@ComponentScan( basePackages = {“south.block”} ) 或者@ComponentScan( value = {“south.block”} ) 指定要扫描的包。

includeFilters 是一个 Filter[] ,表示包括的类型,可以使用注解类型、指定的类型、正则表达式、AspectJ表达式、自定义类等。但是,默认会开启一个默认的扫描所有的被@Component、@Repository、@Service、@Comtroller标注的类的过滤器,因此我们通常需要使用useDefaultFilters = false关闭

excludeFilters 也是一个 Filter[] ,表示排除的类型,同上

在设置包括或排除过滤器时,我们如果使用根据注解类型排除需要注意@Component与@Repository、@Service、@Comtroller的包括关系

自定义TypeFilter

上面代码中,我们的排除过滤器规则是自定义实现TypeFilter接口的一个类

我们可以获取类的元信息,自定义匹配规则,包含或排除一些组件

public class scanFilter implements TypeFilter {
    /**
     * 判断是否匹配。
     * @param metadataReader 元信息阅读器,可以获取类的相关信息
     * @param metadataReaderFactory 元信息阅读器工厂(比如父类或接口等),可以获取任何类的元信息阅读器
     * @return 返回真,则表示符合过滤器,否则不符合
     * @throws IOException
     */
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        // resource对象记录着一些文件存储上的信息
        Resource resource = metadataReader.getResource();
        // annotationMetadata 记录着一些类的注解相关的信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        // classMetadata 记录着关于类的一些信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        String className = classMetadata.getClassName();
        boolean isEr = className.contains("er");
        return isEr;
    }
}

@Scope

使用@Scope注解来表示组件的作用域

基础的有两种,singleton和prototype,分别表示单例和多例

Web环境中,还有request和session,分别表示每个请求对应一个和每个session对应一个

单例默认是在容器创建的时候直接创建

多例则默认不会

@Lazy()

我们使用@Lazy()来设置组件是否懒加载,默认true

@Lazy(false)则表示非懒加载,也就是容器创建时就生成对象

@Lazy(true)则表示懒加载,只有在用时才会去创建对象

@Conditional

可以修饰类或方法,修饰类表示条件满足时,才会将这个类中的组件加入容器。修饰方法表示条件满足时,才会将方法表示的组件加入容器

@Conditional()其中传入一个Condition实现类的Class对象集合

如下,表示window系统创建bill对象,linux系统创建linux对象

    @Conditional({ WinCondition.class })
    @Bean
    public People linux(){
        return new People("linux",null,null);
    }
    
    @Conditional({ Linux.class })
    @Bean
    public People bill(){
        return new People("bill",null,null);
    }

其中,WinCondition类如下

public class WinCondition implements Condition {
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // Bean注册中心
        BeanDefinitionRegistry registry = context.getRegistry();
        // 资源加载器
        ResourceLoader resourceLoader = context.getResourceLoader();
        // 类加载器
        ClassLoader classLoader = context.getClassLoader();
        // bean工厂(容器)
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        // 环境信息
        Environment environment = context.getEnvironment();

        String os = environment.getProperty("os.name");
        if (os.contains("Windows")){
            return true;
        }
        return false;
    }
}

LinuxCondition类似省略

@Import

加在类上,将组件快速导入容器中

  1. 可以加类的Class对象,如:@Import(Cat.class)表示将Cat类加入容器中,组件名为类的全路径名
  2. 可以加一个ImportSelector的实现类,返回需要添加组件的全类名
  3. 可以加一个ImportBeanDefinitionRegistrar的实现类,直接在其方法中注册组件

使用@Import导入

@Import({Cat.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})

ImportSelector实现类

public class MyImportSelector implements ImportSelector {
    /**
     * 选择要导入的Bean
     * @param importingClassMetadata 当前标注@Import注解的类的注解元信息
     * @return 要注册的组件的全路径
     */
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"south.block.pojo.User"};
    }
}

ImportBeanDefinitionRegistrar实现类

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        // 判断是否含有people2组件
        boolean existPeople2 = registry.containsBeanDefinition("people2");
        if (existPeople2) {
            // 设置好组件的类信息
            RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(User.class);
            // 注册并且为组件命名为user
            registry.registerBeanDefinition("userRegistrar",rootBeanDefinition);
        }
    }
}

FactoryBean

其实更像一个工厂,用于生产某种Bean

自定义类实现FactoryBean接口即可

public class ColorFactory implements FactoryBean<Color> {

    public Color getObject() throws Exception {
        return new Color();
    }
	
    public Class<?> getObjectType() {
        return Color.class;
    }
	// 重写的默认方法,其余为实现
    public boolean isSingleton() {
        return true;
    }
}

从容器中获取ColorFactory实例时,会去调用getObject()方法获取Color实例对象。当然如果是单例模式,则并不会每次都去调用getObject()方法

如果我们想要从容器中获取ColorFactory对象时,可以在bean名称前加一个&,例如想要获取ColorFactory对象,Object bean = context.getBean("&colorFactory");

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值