>>分享流行的Java框架以及开源软件,对孙卫琴的《精通Spring:Java Web开发技术详解》提供技术支持 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 16237 个阅读者 刷新本主题
 * 贴子主题:  深入理解spring注解之@ComponentScan注解 回复文章 点赞(0)  收藏  
作者:flybird    发表时间:2020-12-27 00:57:23     消息  查看  搜索  好友  邮件  复制  引用

     今天主要从以下几个方面来介绍一下@ComponentScan注解:
  •   @ComponentScan注解是什么
  • @ComponentScan注解的详细使用
            1.@ComponentScan注解是什么

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

          2.@ComponentScan注解的详细使用

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

     在包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开发的同学经常使用此方式的原因了

               上面只是简单的介绍了@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;
}

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

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

                 测试结果如下:

   mainScanConfig
userDao
userService

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

               演示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容器中

                好了includeFilters参数就演示到这,  另外一个参数excludeFilters和includeFilters用户一摸一样,只是他是   过滤出不加入  spring容器中 ,感兴趣的同学可以自己试试,我这边就不演示了

                  总结一下@ComponentScan的常用方式如下          
  •    自定扫描路径下边带有@Controller,@Service,@Repository,@Component注解加入spring容器
  •    通过includeFilters加入扫描路径下没有以上注解的类加入spring容器
  •   通过excludeFilters过滤出不用加入spring容器的类
  •    自定义增加了@Component注解的注解方式
      最后一种方式这边没有演示,算留给大家的一个小问题吧,感兴趣的同学自己实现下, 有疑问也欢迎留言

     以上是今天文章的所有内容,欢迎大家吐槽

              点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小




                          

----------------------------
原文链接:https://blog.51cto.com/4247649/2118342

程序猿的技术大观园:www.javathinker.net



[这个贴子最后由 flybird 在 2021-06-12 16:28:00 重新编辑]
网站系统异常


系统异常信息
Request URL: http://www.javathinker.net/WEB-INF/lybbs/jsp/topic.jsp?postID=3617

java.lang.NullPointerException

如果你不知道错误发生的原因,请把上面完整的信息提交给本站管理人员