一个个Bean使用@Bean注解注入Spring IoC 很麻烦,好在Spring允许我们进行扫描装配Bean
到IoC容器中,对于扫描装配而言使用的注解是 @Component 和@ComponentScan。
@Component 是标注哪个类被扫描进入 Spring IoC 容器,
@ComponentScan 则是标明采用何种策略去扫描装配Bean。
默认 @ComponentScan 只会扫描当前包和子包
@ComponentScan 源码如下:
// IntelliJ API Decompiler stub source generated from a class file
// Implementation of methods is not available
package org.springframework.context.annotation;
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE})
@java.lang.annotation.Documented
public @interface ComponentScan {
//定义扫描的包
@org.springframework.core.annotation.AliasFor("basePackages")
java.lang.String[] value() default {};
// 定义扫描的包
@org.springframework.core.annotation.AliasFor("value")
java.lang.String[] basePackages() default {};
//定义扫描的类
java.lang.Class<?>[] basePackageClasses() default {};
//bean 的name生成器
java.lang.Class<? extends org.springframework.beans.factory.support.BeanNameGenerator> nameGenerator() default org.springframework.beans.factory.support.BeanNameGenerator.class;
//作用域解析器
java.lang.Class<? extends org.springframework.context.annotation.ScopeMetadataResolver> scopeResolver() default org.springframework.context.annotation.AnnotationScopeMetadataResolver.class;
//作用域代理模式
org.springframework.context.annotation.ScopedProxyMode scopedProxy() default org.springframework.context.annotation.ScopedProxyMode.DEFAULT;
//资源匹配模式
java.lang.String resourcePattern() default "**/*.class";
//是否启用默认的过滤器
boolean useDefaultFilters() default true;
//当满足过滤器的条件时扫描
org.springframework.context.annotation.ComponentScan.Filter[] includeFilters() default {};
//当不满足过滤器的条件时扫描
org.springframework.context.annotation.ComponentScan.Filter[] excludeFilters() default {};
//是否延迟初始化
boolean lazyInit() default false;
//定义过滤器
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target({})
static @interface Filter {
org.springframework.context.annotation.FilterType type() default org.springframework.context.annotation.FilterType.ANNOTATION;
@org.springframework.core.annotation.AliasFor("classes")
java.lang.Class<?>[] value() default {};
@org.springframework.core.annotation.AliasFor("value")
java.lang.Class<?>[] classes() default {};
java.lang.String[] pattern() default {};
}
}
上面的代码中,首先可以通过配置项basePackages 定义扫描的包名,在没有定义的情况下
它只会扫描当前包和报下的路径;还可以通过basePackageClasses 定义 扫描的类;其中还有
includeFilters 和 excludeFilter ,includeFilter定义满足过滤器Filter条件的才去扫描,
excludeFilters则是排除过滤器的条件的Bean。他们都需要@Filter去定义。
它有一个type类型,可以定义为注解,或者正则等类型。classes定义注解类。
pattern定义正则类。
示例:
User.java
package com.didispace.bean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("iuser")
public class User {
@Value("1")
private Long id;
@Value("user_name_1")
private String userName;
@Value("note_1")
private String note;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
}
AppConfig.java
package com.didispace.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
//@Configuration 代表这时一个java配置文件,
// spring的 容器会根据它来生成IoC容器装配Bean
// @ComponentScan excludeFilers 排除使用@Service 的类
@Configuration
@ComponentScan(basePackages = { ”com.didispace.*” } ,
excludeFilters = {@Filter(classes = Service.class) ))
public class AppConfig {
}
IoCTest.java
package com.didispace;
import com.didispace.bean.User;
import com.didispace.config.AppConfig;
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class IoCTest {
private static Logger log = Logger.getLogger(IoCTest.class);
public static void main (String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
User user = ctx.getBean(User.class);
log.info(user.getUserName());
}
}