组件注册相关注解:相当于xml文档中的标签
示例及运行结果:
@ComponentScan(value = "cn.zsm" , includeFilters = {@Filter(type = FilterType.ANNOTATION , classes = {Controller.class, Service.class})} , useDefaultFilters = false)
@Configuration("config")
public class SpringCondiguration {
@Lazy
@Scope("singleton")
@Bean(name = "person", initMethod = "m1" , destroyMethod = "m2")
@Conditional(MethodCondition.class)
public Person person(){
return new Person();
}
@Scope("prototype")
@Bean
@Conditional(MethodCondition.class)
public Book book(){
return new Book();
}
}
重点看一下@Conditional注解中的MethodCondition.class
public class MethodCondition implements Condition {
public boolean matches(ConditionContext context,
AnnotatedTypeMetadata metadata) {
MultiValueMap<String,Object> attributes = metadata.getAllAnnotationAttributes("org.springframework.context.annotation.Scope");
Set<String> keySet = attributes.keySet();
for(String s : keySet){
List<Object> list = attributes.get(s);
if("value".equals(s) && "singleton".equals(String.valueOf(list.get(0))))
return true;
}
return false;
}
}
运行结果:
各注解的作用:
@Configuration用于类上,标识该类是一个配置类。被该注解标注的类,相当于一个XML配置文件。
@Target(ElementType.TYPE) //作用于类上
@Retention(RetentionPolicy.RUNTIME) //运行时由JVM保存
@Documented
@Component
public @interface Configuration {
String value() default "";//指定配置类注册进Spring的bean的名称,默认为类名首字母小写
}
@Bean作用于方法或用于注解类型声明。将方法的返回值注入Spring容器中,默认注入的bean的名称为方法名。
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
@AliasFor("name") //name属性的别名
String[] value() default {}; //指定注入Spring容器的bean的名字,数组类型,可以有多个名字
@AliasFor("value") //value属性的别名
String[] name() default {};
Autowire autowire() default Autowire.NO; //依赖项是通过基于约定的自动装配按名称或类型注入
String initMethod() default ""; //指定初始化方法
String destroyMethod() default AbstractBeanDefinition.INFER_METHOD; //指定销毁方法
}
@Component 用于类,将标注类注入到Spring容器中。@Controller、@Service等注解都有该注解标注。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Component {
String value() default ""; //指定注入bean的名称,默认为类名首字母小写
}
@ComponentScan 用于配置类,扫描指定的包,默认会装配标识了@Controller,@Service,@Repository,@Component注解的类到spring容器中
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
@AliasFor("basePackages")
String[] value() default {}; //扫描的包的路径,数组类型
@AliasFor("value")
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {}; //指定具体的扫描的类
//bean名称的生成器 默认的是BeanNameGenerator
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
// 处理检测到的bean的scope范围
Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
//是否为检测到的组件生成代理
ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
//控制符合组件检测条件的类文件 默认是包扫描下的 **/*.class
String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;
//是否对带有@Component @Repository @Service @Controller注解的类开启检测,默认是开启的
boolean useDefaultFilters() default true;
//指定包含定义Filter满足条件的组件,还要设置useDefaultFilters = false,关闭默认过滤规则
Filter[] includeFilters() default {};
// 排除某些过来器扫描到的类
Filter[] excludeFilters() default {};
//懒加载
boolean lazyInit() default false;
@Retention(RetentionPolicy.RUNTIME)
@Target({})
@interface Filter {
/*
FilterType有5种类型如:
ANNOTATION, 注解类型 默认
ASSIGNABLE_TYPE,指定固定类
ASPECTJ, ASPECTJ类型
REGEX,正则表达式
CUSTOM,自定义类型
*/
FilterType type() default FilterType.ANNOTATION; //过滤规则
@AliasFor("classes")
Class<?>[] value() default {}; //指定要过滤的类名
@AliasFor("value")
Class<?>[] classes() default {};
//用于过滤器的模式(或多个模式),作为指定类 value 的替代方法。
String[] pattern() default {};
}
}
@ComponentScans 用于类,指定多个@ComponentScan策略
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface ComponentScans {
ComponentScan[] value();
}
@Scope 用于类或方法,指定bean的作用域
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scope {
@AliasFor("scopeName")
String value() default "";
/**
*prototype 多实例,bean被调用时才被创建
*singleton 单例,默认容器启动时创建
*request 同一个请求一个实例
*session 同一个session一个实例
*/
@AliasFor("value")
String scopeName() default "";
//指定组件是否应配置为作用域代理,如果是,则该代理应基于接口还是基于子类
ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
}
@Lazy 可用于类、方法、构造函数、参数、属性,懒加载即使用时再对标注的信息进行初始化
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Lazy {
boolean value() default true;
}
@Conditional 用于类或方法 ,根据自定义的条件动态的选择是否加载该bean到springIOC容器中。
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
Class<? extends Condition>[] value(); //指定条件类,继承Condition接口
}
public interface Condition {
/**
* @param context 条件上下文
* @param metadata 注释信息
* @return true 表示条件通过,注册组件; false条件不通过,结束。
*/
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
@Import 用于类,将组件快速导入到组件中
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
//可导入配置类、ImportSelector接口、ImportBeanDefinitionRegistrar接口、或者常规类组件
Class<?>[] value();
}
public interface ImportSelector {
/**
*返回需要导入容器的全类型信息数组,cn.zsm.entity.Book
*AnnotationMetadata:当前标注@import注解的类的所有注解信息
*/
String[] selectImports(AnnotationMetadata importingClassMetadata);
}
public interface ImportBeanDefinitionRegistrar {
/**
* AnnotationMetadata:@import注解标注的类的所有注解信息
* BeanDefinitionRegistry:BeanDefinition注册类,把需要添加的bean调用
* BeanDefinitionRegistry.registerBeanDefinition手动注册进容器
*/
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
}
FactoryBean<T>接口,创建T的实例bean:
public interface FactoryBean<T> {
T getObject() throws Exception; //获取T实例,将T注入容器
Class<?> getObjectType(); //返回FactoryBean创建的对象的类型,如果不知道,返回null
boolean isSingleton(); //是否单例创建T的实例
}
示例:
public class BookFactoryBean implements FactoryBean<Book> {
public Book getObject() throws Exception {
return new Book();
}
public Class<?> getObjectType() {
return null;
}
public boolean isSingleton() {
return false;
}
}
@Configuration
public class SpringCondiguration {
@Bean
public BookFactoryBean bookFactoryBean(){
return new BookFactoryBean();
}
}
测试类:
@Test
public void test() {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringCondiguration.class);
Object book = applicationContext.getBean("bookFactoryBean");
Object bookFactory = applicationContext.getBean("&bookFactoryBean");
System.out.println("book的class类型为: "+book.getClass().getName());
System.out.println("bookFactory的class类型为: "+bookFactory.getClass().getName());
}
结果:
从结果中可以看出,@Bean注册进Spring容器的实例名bookBeanFactory,注册的是BookFactoryBean,但是bookBeanFactory的类型确实Book.class。而BookBeanFactory注册进Spring容器的实例为&bookFactoryBean。