Spring常用注解之组件注册相关注解

Spring应用中注册组件通常有两种方式,一种是通过xml配置的方式,指定id和class进行组件注册,另外一种就是通过使用JavaConfig进行组件的注册,本篇文章将结合具体实例重点介绍第二种方式中注册组件时常用的注解及注解中的常用属性。

1.@Configuration注解

1.1 @Configuration常用属性介绍

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
   // 该value属性一般不需要指定,表示当前注解继承过来的注解,使用该注解标注在
   //   类上之后,该注解就有了@Component注解的作用,将标注的类作为一个组件
   @AliasFor(annotation = Component.class)
   String value() default "";
}

1.2 @Configuration注解使用示例

// 该Class上面标注了@Configuration之后,表示该类为一个JavaConfig配置类
@Configuration
public class BeanConfig {
}

2.@Bean注解

2.1 @Bean常用属性介绍

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
   // 用来指定bean的名称,当声明bean的名称时没有指定属性名,将会使用该属性
   // 例如:@Bean("myCustomer")
   @AliasFor("name")
   String[] value() default {};

   // 用来表示bean的名称,可以在@Bean中显示使用该属性指定bean的名称
   @AliasFor("value")
   String[] name() default {};
   
   // bean的自动注入模型,包括三种:不自动注入,按类型注入,按名称注入
   @Deprecated
   Autowire autowire() default Autowire.NO;
   
   // 表示是否使用候选bean,使用了autowire指定了自动注入模式的bean,在spring
   //   实例化bean的时候就会去查找这些标记了自动注入的bean,这些bean就是候选bean
   //   此处可以设置是否在初始化时使用这些候选bean,默认是使用
   boolean autowireCandidate() default true;
   
   // 指定bean的初始化方法,在bean实例化及属性赋值完成之后会执行
   String initMethod() default "";
   
   // 指定bean的自动销毁方法,在bean的生命周期完成之后【即:调用容器的close方法时】
   //   会自动执行.
   String destroyMethod() default AbstractBeanDefinition.INFER_METHOD;
}

2.2 @Bean使用示例

@Bean通常配置在@Configuration标注的类内部的方法上面,可以根据逻辑灵活创建指定类型的bean组件。

(1)创建配置类TestConfig

@Configuration
@ComponentScan(basePackages = "com.wb.spring.beans")
public class TestConfig {
   // 指定bean的名称,初始化方法及销毁方法
   @Bean(value = "student", 
      initMethod = "initStudent", 
      destroyMethod = "destoryStudent")
   public Student student() {
      Student s = new Student();
      s.setName(UUID.randomUUID().toString());
      return s;
   }
}

(2)创建Student类

public class Student {
   private String name;
   // 省略掉setter,getter和toString ...

   // 初始化方法,在Student实例创建完,name属性设置完成之后初始化的时候执行
   public void initStudent() {
      System.out.println("Student init...");
   }
   // 在调用容器的close方法关闭容器销毁bean的时候执行
   public void destoryStudent() {
      System.out.println("Student destory...");
   }
}

(3)创建测试类

public class TestConfigTest {
   public static void main(String[] args) {
      AnnotationConfigApplicationContext acx = 
         new AnnotationConfigApplicationContext(TestConfig.class);
      Object student = acx.getBean("student");
      System.out.println("student:" + student);
      acx.close();
   }
}
// 控制台输出结果:
Student init...
student:Student{name='b7052b73-cede-4265-97ba-dc19b0f1205c'}
Student destory...

3.@ComponentScan注解

该注解是用来指定Spring初始化类路径下的组件时,需要扫描的组件类所在的包路径。

3.1 @ComponentScan的常用属性

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
   // 表示需要扫描的组件对应的类路径,可指定多个,和basePackages属性互为别名
   @AliasFor("basePackages")
   String[] value() default {};
   
   // 表示需要扫描的组件对应的包路径,可指定多个,和value属性互为别名
   @AliasFor("value")
   String[] basePackages() default {};
   
   // 指定需要扫的类或者接口的class,扫描的时候会在这些类或者接口的class所属的
   //    包下进行扫描
   Class<?>[] basePackageClasses() default {};
   
   // 用来指定bean名称的生成器,默认为BeanNameGenerator
   Class<? extends BeanNameGenerator> nameGenerator() 
      default BeanNameGenerator.class;
   
   // 用来指定解析@Scope注解的解析器
   Class<? extends ScopeMetadataResolver> scopeResolver() 
      default AnnotationScopeMetadataResolver.class;
   
   // 用来指定类的Scope代理模式
   // 包括的类型有:NO,INTERFACES,TARGET_CLASS
   // a.DEFAULT和NO的作用相同,表示不创建代理
   // b.INTERFACES:表示使用JDK来创建代理
   // c.TARGET_CLASS:表示使用CGLIB来创建代理
   ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
   
   // 配置类的扫描路径,为一个匹配符,匹配特定路径,例如:"**/*.class"
   String resourcePattern() default "**/*.class";
   
   // 指定是否启用对@Controller,@Service,@Repository,@Component注解的类
   //   的自动检测
   boolean useDefaultFilters() default true;

   // 对扫描的包或者类进行过滤,如果满足条件,不论组件类上是不是有注解,
   //   Bean都会被创建
   Filter[] includeFilters() default {};

   // 指定扫描过程中忽略哪些类
   Filter[] excludeFilters() default {};

   // 用来指定是否对指定路径下扫描到的bean进行延迟初始化
   boolean lazyInit() default false;

   // 用来完成includeFilters或者execludeFilters的过滤器注解
   @Retention(RetentionPolicy.RUNTIME)
   @Target({})
   @interface Filter {
      // 指定要使用的过滤类型,默认按照注解进行过滤
      FilterType type() default FilterType.ANNOTATION;
     
      // 指定要过滤的类型
      // a.如果type为FilterType.ANNOTATION,value表示要过滤掉value属性所
      //   指定的类
      // b.如果type为FilterType.ASSIGNABLE_TYPE,value表示要过滤掉的类
      
      // c.如果type为FilterType.CUSTOM,value表示过滤规则,对应一个实现了
      //    TypeFilter接口的过滤规则类.
      @AliasFor("classes")
      Class<?>[] value() default {};

      // 和value的作用相同,classes和value互为别名 
      @AliasFor("value")
      Class<?>[] classes() default {};

      // 该参数主要用来处理type为ASPECTJ和REGEX的类型
      // a.当type为ASPECTJ时,pattern可以用来指定一个ASPECTJ表达式
      // b.当type为REGEX时,pattern可以用来指定一个正则表达式
      String[] pattern() default {};
   }
}

3.2 @ComponentScan使用示例

(1)指定扫描”com.wb.spring.beans”路径下的所有类

@Configuration
@ComponentScan(value = "com.wb.spring.beans")
public class TestConfig {
}

(2)指定扫描StudentDao类和StudentService类所在包下的所有组件

@Configuration
@ComponentScan(basePackageClasses={StudentDao.class,
      StudentService.class})
public class TestConfig {
}

(3)指定扫描”com.wb.spring.beans”下面标注@Service,@Controller的组件

@Configuration
@ComponentScan(value = "com.wb.spring.beans",
  includeFilters={
     @ComponentScan.Filter(type=FilterType.ANNOTATION,class={
        Service.class,Controller.class
     })
   },
   useDefaultFilters=false
)
public class TestConfig {
}

(4)指定扫描”com.wb.spring.beans”下面的所有组件,排除掉标注有@Service注解的类以及名称为StudentDao的类

@Configuration
@ComponentScan(basePackages = "com.wb.spring.beans",
  excludeFilters = {
     @ComponentScan.Filter(type = FilterType.ANNOTATION,
        classes = {Service.class}),
     @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE,
        classes = {StudentDao.class})
  },
  useDefaultFilters = false
)
public class TestConfig {
}

4.@Scope注解

4.1 @Scope的常用属性

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scope {

   /**
    * bean的作用域,和scopeName互为别名
    */
   @AliasFor("scopeName")
   String value() default "";

   /**
    * bean的作用域,和value互为别名
    * Spring的Bean作用域有四种:
    * SCOPE_PROTOTYPE: 多实例,每次获取,都会生成一个新实例
    * SCOPE_SINGLETON: 单实例,多次获取到的都是一个实例
    * SCOPE_REQUEST: web中,每次请求会生成一个实例
    * SCOPE_SESSION: web中,同一个会话中多次获取到的是同一个实例.
    */
   @AliasFor("value")
   String scopeName() default "";
   
   // 用于指定Spring在某些作用域生成代理bean时,创建代理的方式,默认是不创建
   //    代理
   // a.INTERFACES表示使用JDK生成代理,需要代理类去实现接口
   // b.TARGET_CLASS表示使用CGLIB生成代理
   ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
}

4.2 @Scope的使用示例

例:生成一个名称为student的多实例bean。注意:Spring在生成bean的时候,如果没有明确指定,将默认生成单实例bean。

@Configuration
@ComponentScan(basePackages = "com.wb.spring.beans")
public class TestConfig {

   @Bean(value = "student")
   @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
   public Student student() {
      Student s = new Student();
      s.setName(UUID.randomUUID().toString());
      return s;
   }
}

5.@Lazy注解

用来标注某一个bean为延迟创建。延迟创建指的是,Spring在初始扫描类路径下的所有组件并初始化Bean的时候并不会真正去创建标注@Lazy注解额的bean,直到使用的时候才会去创建并初始化。

5.1 @Lazy注解的常用属性

@Target({ElementType.TYPE, // 类
   ElementType.METHOD,  // 方法
   ElementType.CONSTRUCTOR,  // 构造函数
   ElementType.PARAMETER,  // 参数
   ElementType.FIELD}) // 成员变量
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Lazy {
   /**
    * 标记是否为懒加载,默认值为true。所以可以直接标注注解,不指定value属性
    */
   boolean value() default true;
}

5.2 @Lazy注解的使用示例

例:创建一个名称为student的bean,并且为延迟加载

@Configuration
@ComponentScan(basePackages = "com.wb.spring.beans")
public class TestConfig {
   @Bean(value = "student")
   @Lazy
   public Student student() {
      Student s = new Student();
      s.setName(UUID.randomUUID().toString());
      return s;
   }
}

6.@Conditional注解

用来进行条件注入,即:满足条件的bean才会被注入到Spring容器中。

6.1 @Conditional常用属性

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
   // 指定注入bean时使用的条件类,这个类需要实现Condition接口
   Class<? extends Condition>[] value();
}

6.2 @Conditional使用示例

当系统为Linux时,向容器中注入一个名称为LinuxCalc的组件。

(1)创建配置类

@Configuration
@ComponentScan(basePackages = "com.wb.spring.ioc")
public class ConditionalConfig {
   // 添加注入条件
   @Bean("linuxCalc")
   @Conditional(value = LinuxConditional.class)
   public LinuxCalc calc() {
      return new LinuxCalc();
   }
}

(2)创建LinuxCalc组件类

public class LinuxCalc {
}

(3)创建条件类,需要实现Condition接口,并实现matches方法,根据方法返回值判断是否注入对应的组件

public class LinuxConditional implements Condition {
   @Override
   public boolean matches(ConditionContext context, 
      AnnotatedTypeMetadata metadata) {
      Environment environment = context.getEnvironment();
      // 系统名称
      String osName = environment.getProperty("os.name");
      if (osName != null && osName.contains("linux")) {
         return true;
      }
      return false;
   }
}

(3)测试类

public class TestConditional {
   public static void main(String[] args) {
      ApplicationContext acx = 
        new AnnotationConfigApplicationContext(
           ConditionalConfig.class);
      String[] names = acx.getBeanDefinitionNames();
      for (String name : names) {
         System.out.println(name);
      }
   }
}
// 输出结果:
...其他组件名称略
conditionalConfig
linuxCalc

// 如果在linux系统上运行上述测试类,linuxCalc组件将会被注册到容器中
// windows系统则不会注入该组件

7.@Import注解

用来快速地给容器中导入一个组件,在SpringBoot底层大量使用,Spring框架中也大量使用,例如:@EnableTransactionManagement注解中就使用了该注解。

7.1 @Import常用属性

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {

   // 注入的组件对应的class
   Class<?>[] value();
}

7.2 @Import使用示例

例:给容器中快速注入一个类型为MyBeanPostProcessor的组件

(1)实现配置类

@Configuration
@ComponentScan(basePackages = "com.wb.spring.beans")
@Import(value = MyBeanNameAware.class)
public class TestConfig {
}

(2)实现MyBeanNameAware组件类

public class MyBeanNameAware implements BeanNameAware{
   @Override
   public void setBeanName(Stirng name) {
      System.out.println("setBeanName...");
   }
}

(3)创建测试类

public class TestConditional {
   public static void main(String[] args) {
      ApplicationContext acx = 
         new AnnotationConfigApplicationContext(TestConfig.class);
   }
}
// 输出结果:
setBeanName...

至此,Spring组件注册相关常用的注解及常用属性介绍完毕,如有错误,请指正!欢迎转发该文章!

注意:文章属于原创,如果转发请标注文章来源:个人小站【www.jinnianshizhunian.vip

另外提供一些优秀的Java架构师及IT开发视频,书籍资料。无需注册,无需登录即可下载,免费下载地址:https://www.592xuexi.com

1 条思考于 “Spring常用注解之组件注册相关注解

  1. Pingback: Spring常用注解之Bean生命周期相关注解 – 个人小站-记录编程知识