Spring学习(九)-组件添加@ComponentScan-自动扫描

@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);
	}
}

测试结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值