@ComponentScan-自动扫描组:
包扫描、只要标注了@Controller、@Service、@Repository,@Component注解。
xml配置案例:
package com.spring.bean;
public class Person {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Person(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
/**
* 初始化
*/
public void personInitMethod(){
System.out.println("person-------initMethod");
}
/**
* 销毁
*/
public void personDestroyMethod(){
System.out.println("person-------destroyMethod");
}
}
报扫描:
<!-- 包扫描、只要标注了@Controller、@Service、@Repository,@Component
use-default-filters="false":关闭默认扫描规则
-->
<context:component-scan base-package="com.spring"></context:component-scan>
<!-- 初始化person -->
<bean id="person" class="com.spring.bean.Person" scope="prototype" >
<property name="age" value="19"></property>
<property name="name" value="zhangsan"></property>
</bean>
注解类:
@Component
public class MyComponent {
}
@Controller
public class UserController {
}
@Repository
public interface UserDao {
}
@Service
public class UserService {
}
测试类:
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
//项目中使用了xml配置和注解配置 同时配置一个对象,使用如下方式会报错,因为容器注入两个类型一样的对象
// Person bean = applicationContext.getBean(Person.class);
Person bean = (Person)applicationContext.getBean("Myperson");
System.out.println(bean.toString());
//参数是配置类BeanConfig
/* ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
Person bean1 = applicationContext.getBean(Person.class);
System.out.println(bean1);*/
String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
for (String name : namesForType) {
System.out.println("beanId------"+name);
}
System.out.println("容器中的组件");
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
结果:
注解版:
//配置类==配置文件
@Configuration //告诉Spring这是一个配置类
@ComponentScan(value = "com.spring")
public class BeanConfig {
//给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
//initMethod 初始化方法
//destroyMethod 销毁方法
@Bean(name = "Myperson",initMethod = "personInitMethod",destroyMethod = "personDestroyMethod")
public Person Myperson(){
return new Person("zhw", 20);
}
}
测试类:
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
Person bean1 = applicationContext.getBean(Person.class);
System.out.println(bean1);
String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
for (String name : namesForType) {
System.out.println("beanId------"+name);
}
System.out.println("容器中的组件");
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
结果:
ComponentScan源码说明:
package org.springframework.context.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.core.annotation.AliasFor;
import org.springframework.core.type.filter.TypeFilter;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
//扫描路径
@AliasFor("basePackages")
String[] value() default {};
//扫描多个路径
@AliasFor("value")
String[] basePackages() default {};
//包类class
Class<?>[] basePackageClasses() default {};
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;
//判断使用的是否默认拦截
boolean useDefaultFilters() default true;
//includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件
Filter[] includeFilters() default {};
//excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件
Filter[] excludeFilters() default {};
//懒加载
boolean lazyInit() default false;
//自定义拦截
@Retention(RetentionPolicy.RUNTIME)
@Target({})
@interface Filter {
//连接类型
//FilterType.ANNOTATION:按照注解
//FilterType.ASSIGNABLE_TYPE:按照给定的类型;
//FilterType.ASPECTJ:使用ASPECTJ表达式
//FilterType.REGEX:使用正则指定
//FilterType.CUSTOM:使用自定义规则
FilterType type() default FilterType.ANNOTATION;
@AliasFor("classes")
Class<?>[] value() default {};
@AliasFor("value")
Class<?>[] classes() default {};
String[] pattern() default {};
}
}
指定需要扫描的路径和不需要扫描的路径:
@Configuration //告诉Spring这是一个配置类
@ComponentScans(
value = {
@ComponentScan(value="com.spring",includeFilters = {
@ComponentScan.Filter(type= FilterType.ANNOTATION,classes={Controller.class}),
@ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE,classes={UserService.class}
)
},useDefaultFilters = false,excludeFilters = {
/*不注入UserDao*/
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Repository.class)
})
}
)
//@ComponentScan value:指定要扫描的包
//excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件
//includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件
//FilterType.ANNOTATION:按照注解
//FilterType.ASSIGNABLE_TYPE:按照给定的类型;
//FilterType.ASPECTJ:使用ASPECTJ表达式
//FilterType.REGEX:使用正则指定
//FilterType.CUSTOM:使用自定义规则
public class BeanConfig {
//给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
//initMethod 初始化方法
//destroyMethod 销毁方法
@Bean(name = "Myperson",initMethod = "personInitMethod",destroyMethod = "personDestroyMethod")
public Person Myperson(){
return new Person("zhw", 20);
}
}
结果:
自定义扫描:
MyFilter:
public class MyTypeFilter implements TypeFilter {
/**
* metadataReader:读取到的当前正在扫描的类的信息
* metadataReaderFactory:可以获取到其他任何类信息的
*/
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
// TODO Auto-generated method stub
//获取当前类注解的信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描的类的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取当前类资源(类的路径)
Resource resource = metadataReader.getResource();
String className = classMetadata.getClassName();
if(className.contains("onent")){
System.out.println("进入容器中的组件--->"+className);
return true;
}
return false;
}
}
//配置类==配置文件
@Configuration //告诉Spring这是一个配置类
@ComponentScans(
value = {
@ComponentScan(value="com.spring",includeFilters = {
@ComponentScan.Filter(type=FilterType.CUSTOM,classes={MyTypeFilter.class})
},useDefaultFilters = false)
}
)
//@ComponentScan value:指定要扫描的包
//excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件
//includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件
//FilterType.ANNOTATION:按照注解
//FilterType.ASSIGNABLE_TYPE:按照给定的类型;
//FilterType.ASPECTJ:使用ASPECTJ表达式
//FilterType.REGEX:使用正则指定
//FilterType.CUSTOM:使用自定义规则
public class BeanConfig {
//给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
//initMethod 初始化方法
//destroyMethod 销毁方法
@Bean(name = "person",initMethod = "personInitMethod",destroyMethod = "personDestroyMethod")
public Person person(){
return new Person("zhw", 20);
}
}
测试结果: