深入理解spring注解之@ComponentScan注解


深入理解spring注解之@ComponentScan注解
)
今天主要从以下几个方面来介绍一下@ComponentScan注解:

  • @ComponentScan注解是什么
  • @ComponentScan注解的详细使用

1、@ComponentScan注解是什么

其实很简单,@ComponentScan主要就是定义扫描的路径从中找出标识了需要装配的类自动装配到spring的bean容器中

2、@ComponentScan注解的详细使用

做过web开发的同学一定都有用过@Controller,@Service,@Repository注解,查看其源码你会发现,他们中有一个共同的注解@Component,没错@ComponentScan注解默认就会装配标识了@Controller,@Service,@Repository,@Component注解的类到spring容器中,好下面咱们就先来简单演示一下这个例子

2.1 准备数据

在包com.zhang.controller下新建一个UserController带@Controller注解如下:

package com.zhang.controller;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
}

在包com.zhang.service下新建一个UserService带@Service注解如下:

package com.zhang.service;
import org.springframework.stereotype.Service;
@Service
public class UserService {
}

在包com.zhang.dao下新建一个UserDao带@Repository注解如下:

package com.zhang.dao;
import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
}

新建一个配置类如下:

/**
 * 主配置类  包扫描com.zhang
 *
 * @author zhangqh
 * @date 2018年5月12日
 */
@ComponentScan(value="com.zhang")
@Configuration
public class MainScanConfig {
}

新建测试方法如下:

AnnotationConfigApplicationContext applicationContext2 = new AnnotationConfigApplicationContext(MainScanConfig.class);
        String[] definitionNames = applicationContext2.getBeanDefinitionNames();
        for (String name : definitionNames) {
            System.out.println(name);
}

运行结果如下:

mainScanConfig
userController
userDao
userService

怎么样,包扫描的方式比以前介绍的通过@Bean注解的方式是不是方便很多,这也就是为什么web开发的同学经常使用此方式的原因了

2.2 对@ComponentScan的详细解释

上面只是简单的介绍了@ComponentScan注解检测包含指定注解的自动装配,接下来让我们来看看@ComponentScan注解的更加详细的配置,在演示详细的配置之前,让我们先看看@ComponentScan的源代码如下:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
    /**
     * 对应的包扫描路径 可以是单个路径,也可以是扫描的路径数组
     * @return
     */
    @AliasFor("basePackages")
    String[] value() default {};
    /**
     * 和value一样是对应的包扫描路径 可以是单个路径,也可以是扫描的路径数组
     * @return
     */
    @AliasFor("value")
    String[] basePackages() default {};
    /**
     * 指定具体的扫描的类
     * @return
     */
    Class<?>[] basePackageClasses() default {};
    /**
     * 对应的bean名称的生成器 默认的是BeanNameGenerator
     * @return
     */
    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
    /**
     * 处理检测到的bean的scope范围
     */
    Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
    /**
     * 是否为检测到的组件生成代理
     * Indicates whether proxies should be generated for detected components, which may be
     * necessary when using scopes in a proxy-style fashion.
     * <p>The default is defer to the default behavior of the component scanner used to
     * execute the actual scan.
     * <p>Note that setting this attribute overrides any value set for {@link #scopeResolver}.
     * @see ClassPathBeanDefinitionScanner#setScopedProxyMode(ScopedProxyMode)
     */
    ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
    /**
     * 控制符合组件检测条件的类文件   默认是包扫描下的  **/*.class
     * @return
     */
    String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;
    /**
     * 是否对带有@Component @Repository @Service @Controller注解的类开启检测,默认是开启的
     * @return
     */
    boolean useDefaultFilters() default true;
    /**
     * 指定某些定义Filter满足条件的组件 FilterType有5种类型如:
     *                                  ANNOTATION, 注解类型 默认
                                        ASSIGNABLE_TYPE,指定固定类
                                        ASPECTJ, ASPECTJ类型
                                        REGEX,正则表达式
                                        CUSTOM,自定义类型
     * @return
     */
    Filter[] includeFilters() default {};
    /**
     * 排除某些过来器扫描到的类
     * @return
     */
    Filter[] excludeFilters() default {};
    /**
     * 扫描到的类是都开启懒加载 ,默认是不开启的
     * @return
     */
    boolean lazyInit() default false;
}

2.3 案例

2.3.1 basePackageClasses

演示basePackageClasses参数,如我们把配置文件改成如下

@ComponentScan(value="com.zhang.dao",useDefaultFilters=true,basePackageClasses=UserService.class)
@Configuration
public class MainScanConfig {
}

测试结果如下:

mainScanConfig
userDao
userService

只有userDao外加basePackageClasses指定的userService加入到了spring容器中

2.3.2 includeFilters

在com.zhang.service包下新建一个UserService2类如下:注意没有带@Service注解

package com.zhang.service;
public class UserService2 {
}

配置类改成:

@ComponentScan(value="com.zhang",useDefaultFilters=true,
    includeFilters={
        @Filter(type=FilterType.ANNOTATION,classes={Controller.class}),
        @Filter(type=FilterType.ASSIGNABLE_TYPE,classes={UserService2.class})
    })
@Configuration
public class MainScanConfig {
}

运行结果如下:

mainScanConfig
userController
userDao
userService
userService2

userService2同样被加入到了spring容器
新增一个自定义的实现了TypeFilter的MyTypeFilter类如下:

/**
 * 自定义过滤
 *
 * @author zhangqh
 * @date 2018年5月12日
 */
public class MyTypeFilter implements TypeFilter {
    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();
        System.out.println("--->"+className);
        // 检测名字包含Service的bean
        if(className.contains("Service")){
            return true;
        }
        return false;
    }
}

修改主配置如下:

@ComponentScan(value="com.zhang",useDefaultFilters=true,
    includeFilters={
        @Filter(type=FilterType.ANNOTATION,classes={Controller.class}),
        @Filter(type=FilterType.CUSTOM,classes={MyTypeFilter.class})
    })
@Configuration
public class MainScanConfig {
}

运行结果如下:

mainScanConfig
userController
userDao
userService
userService2

可以发现同样userService2被加入到了spring容器中

3、总结

总结一下@ComponentScan的常用方式如下

  • 自定扫描路径下边带有@Controller,@Service,@Repository,@Component注解加入spring容器
  • 通过includeFilters加入扫描路径下没有以上注解的类加入spring容器
  • 通过excludeFilters过滤出不用加入spring容器的类
  • 自定义增加了@Component注解的注解方式
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值