Sping中的@ComponentScan注解

@ComponentScan主要就是定义扫描的路径从中找出标识了需要装配的类自动装配到spring的bean容器中。@ComponentScan默认会装配标识了@Controller,@Service,@Repository,@Component注解的类到spring容器中。如果你指定了路径,Spring将会将在被指定的包及其子的包中寻找bean。如果没有指定路径Spring默认的在@ComponentScan注解所在的包及其子包中寻找bean。@ComponentScan注解相当于在配置文件中的 <context:component-scan>标签。

@ComponentScan注解

配置类:

import org.springframework.context.annotation.ComponentScan;

@ComponentScan
public class MyConfig {

}

测试类:

import io.mieux.config.BeanConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test {
    public static void main(String[] args) {
        ApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(MyConfig.class);
		// 使用 ApplicationContext的getBeanDefinitionNames()方法获取已经注册到容器中的bean的名称。
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for (String beanName : beanDefinitionNames) {
            System.out.println("beanName: " + beanName);
        }
    }
}

结果:

beanName: org.springframework.context.annotation.internalConfigurationAnnotationProcessor
beanName: org.springframework.context.annotation.internalAutowiredAnnotationProcessor
beanName: org.springframework.context.annotation.internalRequiredAnnotationProcessor
beanName: org.springframework.context.annotation.internalCommonAnnotationProcessor
beanName: org.springframework.context.event.internalEventListenerProcessor
beanName: org.springframework.context.event.internalEventListenerFactory
beanName: myConfig

除了 spring 本身注册的一些 bean 之外,可以看到最后一行,已经将 MyConfig 这个类注册进容器中了。

属性作用
value用于指定包的路径,进行扫描
basePackages用于指定包的路径,进行扫描
basePackageClasses用于指定某个类的包的路径进行扫描
nameGeneratorbean的名称的生成器
useDefaultFilters是否开启对@Component,@Repository,@Service,@Controller的类进行检测
includeFilters包含的过滤条件(使用@Filter注解)
excludeFilters排除的过滤条件,用法和includeFilters一样
添加多种扫描规则

1.如果使用的 jdk8,则可以直接添加多个 @ComponentScan 来添加多个扫描规则,但是在配置类中要加上 @Configuration 注解,否则无效。

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@ComponentScan(value = "com.czx.controller")
@ComponentScan(value = "com.czx.service")
@Configuration
public class MyConfig {
	...
}

2.使用 @ComponentScans 来添加多个 @ComponentScan,从而实现添加多个扫描规则。同样,也需要加上 @Configuration 注解,否则无效。

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;
import org.springframework.context.annotation.Configuration;

@ComponentScans(value = 
        {@ComponentScan(value = "com.czx.controller"),
        @ComponentScan(value = "com.czx.service")})
@Configuration
public class MyConfig {

}
@Filter注解

过滤器的扫描条件:

1,type=FilterType.ANNOTATION 按照注解的方式进行扫描.后面classes属性为注解的类型,如:

@Configuration//标记此类为配置类
@ComponentScan(value="com.wxj",excludeFilters= {
        @Filter(type=FilterType.ANNOTATION,classes= {Controller.class})
})
public class MainConfig {
    //将标有@Controller注解的类排除在外不会加载到容器中来
}

2,type=FilterType.ASSIGNABLE_TYPE,按照指定的类,进行过滤,后面的classes属性的值为"类名.class".如:

@Configuration//标记此类为配置类
@ComponentScan(value="com.wxj",
includeFilters= {
        @Filter(type=FilterType.ASSIGNABLE_TYPE,classes= {BookService.class})
},useDefaultFilters=false)
public class MainConfig {
    //只会加载BookService,以及BookService的子类或者其实现类
}

3,type=FilterType.CUSTOM,按照自己自定义的方式来进行过滤和筛选(使用此过滤类型,虽然比较繁琐,但是使用起来完全可以由自己来定义扫描的规则)

首先定义@Filter注解的类型:

@Configuration//标记此类为配置类
@ComponentScan(value="com.wxj",
includeFilters= {@Filter(type=FilterType.CUSTOM,classes{MyTypeFilter.class})
},useDefaultFilters=false)
public class MainConfig {
}

MyTypeFilter即为自己定义的匹配方法,其中MyTypeFilter类中的match方法的返回值为true时,为符合过滤条件,如果返回为false,则不符合过滤条件,代码如下:

public class MyTypeFilter implements TypeFilter {

    /**
     * MetadataReader metadataReader:获取当前正在扫描的类的信息
     * MetadataReaderFactory metadataReaderFactory,获取带其他任何类的信息
     */
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();//获取当前类的注解信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();//获取当前扫描的类信息
        Resource resource = metadataReader.getResource();//获取当前扫描的资源信息
        String name = classMetadata.getClassName();//获取类的名字
        if(name.contains("er")) {
            return true;//如果类的名字中带有"er",则符合过滤的要求
        }
        return false;
    }

}

注:TypeFilter中的ASPECTJ和REGEX(正则方式),没有介绍,使用较少,有兴趣可以自行研究.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值