Spring IOC 容器常见底层注解使用

通过上一篇文章《Spring框架基本结构介绍》,已经对Spring的结构已经有了大概的了解

接下来学习Spring IOC 容器底层注解使用。

 

一、 Bean的定义方式

①XML配置文件的形式

 

1
2
3
4
5
6
7

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    //定义一个Bean的信息 
    <bean id="car" class="com.smallmouse.compent.Cat"></bean> 
</beans>

 

 

1
2
3
4
5

public static void main( String[] args ) 
    { 
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); 
        System.out.println(ctx.getBean("person")); 
    }

 

②Java配置类的形式

1. @Bean

 

1
2
3
4

    @Bean(initMethod = "init", destroyMethod = "destory") //指定这个Bean的创建方法以及销毁方法,方法写在Bean的实体里
    public Tiger tiger() {
        return new Tiger();
    }

 

通过@Bean的形式是使用的话, bean的默认名称是方法名,若要指定Bean的名字需要通过@Bean(value=”bean的名称”)这种方式来指定。

1.1: initMethod 指定Bean的初始化方法

1.2: destroyMethod 指定Bean的销毁方法(多实例的Bean销毁由GC处理,不受容器控制)

注:Bean的其他几种初始化方法放在GitHub的代码中,本文不多做解释,链接在文末

2. @Scpoe

配置Bean的作用域对象,在不指定@Scope的情况下,所有的bean都是单实例的bean,而且是饿汉加载(容器启动实例就创建好了),指定@Scope为 prototype 表示为多实例、懒汉模式加载(IOC容器启动的时候,并不会创建对象,而是在第一次使用的时候才会创建)

@Scope指定作用域的几种方法:
a) singleton  单实例的(默认)
b) prototype 多实例的
c) request  同一次请求
d) session  同一个会话级别

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14

/**
     * 指定@Scope为 prototype 表示为多实例的,而且还是懒汉式加载
     * singleton 单实例的(默认)
     * prototype 多实例的
     * request 同一次请求
     * session 同一个会话级别
     *
     * @return
     */
    @Bean
    @Scope(value = "prototype")
    public Mouse mouse() {
        return new Mouse();
    }

 

3.@Lazy

懒加载(主要针对单实例的bean 容器启动的时候,不创建对象,在第一次使用的时候才会创建该对象)

 

1
2
3
4
5
6

//使@Bean变成单例,懒汉式加载
    @Bean
    @Lazy
    public Dog dog() {
        return new Dog();
    }

 

4.@Conditional

用于进行条件判断等,用法如下

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

   @Bean
    @Conditional(value = beanConditional.class)
    public Dog dog() {
        return new Dog();
    }

    class beanConditional implements Condition {//实现Condition接口

        @Override
        public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
            if (conditionContext.getBeanFactory().containsBean("cat")) {//判断cat是否在容器中
                return true; //如果在容器中才会创建
            }
            return false;//不在则不创建
        }
    }

 

二、向IOC 容器中添加组件的方式

1.@CompentScan

在配置类上写@CompentScan注解来进行扫描指定包,包含(@Controller  @Service@Respository  @Compent)的组件,并添加到容器中。

1
2
3
4
5

@Configuration
@ComponentScan(basePackages = {"org.smallmouse.scan"})
public class ScanConfig {

}

1.1: 排除方法  excludeFilters

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

@Configuration
/**
 * 注解形式的FilterType.ANNOTATION @Controller @Service @Repository @Compent
 * 指定类型的 FilterType.ASSIGNABLE_TYPE
 * aspectj类型的 FilterType.ASPECTJ(不常用)
 * 正则表达式的 FilterType.REGEX(不常用)
 * 自定义的 FilterType.CUSTOM
 */
@ComponentScan(basePackages = {"org.smallmouse.scan"},excludeFilters = {
    @ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Controller.class}),
    @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value = {DogDao.class})
})//扫描时过滤掉@Controller和DogDao类型
public class ScanConfig {

}

 

1.2: 包含方法 includeFilters (若使用包含的用法,需要把useDefaultFilters属性设置为false,true表示扫描全部)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

@Configuration
/**
 * 注解形式的FilterType.ANNOTATION @Controller @Service @Repository @Compent
 * 指定类型的 FilterType.ASSIGNABLE_TYPE
 * aspectj类型的 FilterType.ASPECTJ(不常用)
 * 正则表达式的 FilterType.REGEX(不常用)
 * 自定义的 FilterType.CUSTOM
 */
@ComponentScan(basePackages = {"org.smallmouse.scan"},includeFilters = {
    @ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Repository.class}),
    @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value = {CatDao.class})
},useDefaultFilters = false)//引入@Repository和CatDao类型,引入时要将useDefaultFilters(默认为true,表示扫描全部)设置成false
public class ScanConfig {

}

 

1.3: @ComponentScan.Filter FilterType的类型

a)注解形式的FilterType.ANNOTATION ( @Controller @Service @Repository @Compent )
b)指定类型的 FilterType.ASSIGNABLE_TYPE                                                @ComponentScan.Filter(type =FilterType.ASSIGNABLE_TYPE,value = {CatService.class})
c)aspectj类型的   FilterType.ASPECTJ(不常用,不做过多赘述)
d)正则表达式类型的   FilterType.REGEX(不常用,不做过多赘述)
e)自定义的  FilterType.CUSTOM

1.4: FilterType.CUSTOM 使用方法

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

//自定义的FilterType需要实现TypeFilter接口
public class ZooFilterType implements TypeFilter {

  @Override
  public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
      throws IOException {
    //获取当前注解源信息
    AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
    //获取当前类class源信息
    ClassMetadata classMetadata = metadataReader.getClassMetadata();
    //获取当前类资源信息
    Resource resource = metadataReader.getResource();

    if (classMetadata.getClassName().contains("dao")) {
      System.out.println("print true");
      return true; //返回true的时候才会执行includeFilters或excludeFilters的逻辑
    }
    return false;//返回false的时候@ComponentScan只会扫描到自身
  }
}

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

@Configuration
/**
 * 注解形式的FilterType.ANNOTATION @Controller @Service @Repository @Compent
 * 指定类型的 FilterType.ASSIGNABLE_TYPE
 * aspectj类型的 FilterType.ASPECTJ(不常用)
 * 正则表达式的 FilterType.REGEX(不常用)
 * 自定义的 FilterType.CUSTOM
 */
@ComponentScan(basePackages = {"org.smallmouse.scan"},includeFilters = {
    @ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Repository.class}),
    @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value = {CatDao.class}),
    @ComponentScan.Filter(type = FilterType.CUSTOM,value = {ZooFilterType.class})//设置自定义的FilterType类
},useDefaultFilters = false)//引入@Repository和CatDao类型,引入时要将useDefaultFilters(默认为true,表示扫描全部)设置成false
public class ScanConfig {

}

 

2.@Bean(这种方式在上面已经有讲过,此处就不多做赘述)

3.@Import (导入组件的id为全类名路径)

 

1
2
3
4
5

@Configuration
@Import(value = {Cat.class,Mouse.class,ZooImportSelector.class,ZooBeanDefinitionRegister.class})
public class ImportConfig {

}

 

3.1: 通过@Import 的ImportSeletor类实现组件的导入 (导入组件的id为全类名路径)

 

1
2
3
4
5
6
7
8

public class ZooImportSelector implements ImportSelector {

  @Override
  public String[] selectImports(AnnotationMetadata annotationMetadata) {
    //可以获取导入类的注解信息
    return new String[]{"org.smallmouse.scan.dao.CatDao","org.smallmouse.scan.dao.MouseDao"};
  }
}

 

3.2: 通过@Import的 ImportBeanDefinitionRegister导入组件(可以指定bean的名称)

 

1
2
3
4
5
6
7
8
9
10
11

public class ZooBeanDefinitionRegister implements ImportBeanDefinitionRegistrar {

  @Override
  public void registerBeanDefinitions(AnnotationMetadata annotationMetadata,
      BeanDefinitionRegistry beanDefinitionRegistry) {
    //创建一个 根定义Bena 的对象
    RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Dog.class);
    //将根定义Bena对象导入到容器中
    beanDefinitionRegistry.registerBeanDefinition("dog", rootBeanDefinition);//自定义Bean的name,放入对应根定义Bena对象
  }
}

 

4. 通过实现FacotryBean接口注册组件

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

public class TigerFactoryBean implements FactoryBean<Tiger> {

  //返回Bean的对象
  @Override
  public Tiger getObject() throws Exception {
    return new Tiger();
  }

  //返回Bean的类型
  @Override
  public Class<?> getObjectType() {
    return Tiger.class;
  }

  //是否为单例
  @Override
  public boolean isSingleton() {
    return false;
  }
}

 

三、其他

1.@Profile

@Profile标识在类上,那么只有当前环境匹配,整个配置类才会生效
@Profile标识在Bean上 ,那么只有当前环境的Bean才会被激活

没有标志为@Profile的bean 不管在什么环境都可以被激活

2. @Configuration

标志着这个类是一个配置类

关于 @Controller @Service @Repository  @Compent @Autowired等,开发中常用到的注解,想必大家对它们的使用已经早就已经熟练甚至精通了,这里就不多做赘述了。

GitHub: https://github.com/LiuTenGg/SpringCommonCoreNotes

内容来源:http://www.tengspace.com/index.php/2019/06/08/spring-ioc-%e5%ae%b9%e5%99%a8%e5%b8%b8%e8%a7%81%e5%ba%95%e5%b1%82%e6%b3%a8%e8%a7%a3%e4%bd%bf%e7%94%a8/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值