SpringBoot 注解大全

@ComponentScan

ComponentScan 使用注释配置来 配置 要扫描类的包 。下面可以扫描com.baeldung.annotations包以及子包:

@Configuration
@ComponentScan(basePackages = "com.baeldung.annotations")
class VehicleFactoryConfig {}

下面会扫描到A.class同级和所在包下面的所有子包类:

@Configuration
@ComponentScan(basePackageClasses = A.class)
class VehicleFactoryConfig {}

ComponentScan 还 利用 Java 8 的重复注解 功能:

@ComponentScan(basePackages  = "com.a")
@ComponentScan(basePackages = "com.b")
class VehicleFactoryConfig {}

上面可以扫描到 : com.a , com.b

java8重复注解Demo:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Authorities.class) // 定义注解可重复
@interface Authority {
    String role();
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Authorities {
    Authority[] value();
}


////////////////////重复注解使用
@Authority(role = "admin")
@Authority(role = "user")
class B {}

public class Test {
    public static void main(String[] args) {
        for (Authority authority : B.class.getAnnotationsByType(Authority.class)) {
            System.out.println(authority.role());
        }
    }
}

//===========打印结果
admin
user

@Configuration

声明一个类,表示该类里面有一个或多个@Bean注解的方法。并且将这些方法返回对象注入到spring。例如:

@Configuration  
public class Vehicle  
{  
// 将Vehicle对象 注入到spring
@Bean  Vehicle engine()  
{  
  return new Vehicle();  
 }  
}  

@Bean

它是一个方法级注释。 它是XML <bean>标记的一种替代。 它会向spring容器中注入bean。


@SpringBootApplication

我们使用这个注解来标记Spring Boot应用程序的主类:

@SpringBootApplication
class VehicleFactoryApplication {
    public static void main(String[] args) {
        SpringApplication.run(VehicleFactoryApplication.class, args);
    }
}

@SpringBootApplication封装了@Configuration、@EnableAutoConfiguration和@ComponentScan注解的默认属性

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
		@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
//......
}

@EnableAutoConfiguration

@EnableAutoConfiguration,顾名思义,启用自动配置。 这意味着Spring Boot在其类路径上查找自动配置bean并自动应用它们。 注意,我们必须在@Configuration中使用这个注释:

@Configuration
@EnableAutoConfiguration
class VehicleFactoryConfig {}  

@DependsOn

DependsOn 注解主要用于指定当前bean所依赖的beans。任何被指定依赖的bean都由Spring保证在当前bean之前创建。

这里有个案例使用DependsOn解决空指针问题:

有个SpringContext 工具类:

@Component
public class App implements BeanFactoryAware {
    private static BeanFactory beanFactory;
    public static BeanFactory getBeanFactory() {
        return beanFactory;
    }
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        Preconditions.checkNotNull(beanFactory);
        App.beanFactory = beanFactory;
    }
    public static Object getBean(String name) throws BeansException {
        // TODO Auto-generated method stub
        return beanFactory.getBean(name);
    }
}

然后在afterPropertiesSet方法直接使用静态方法获取bean:

@Component
public class B implements InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        RestTemplate restTemplate = App.getBean(RestTemplate.class);
        System.out.println(restTemplate);
    }
}

然后直接就报空指针了???

原因就是App 还没有被Spring初始化,beanFactory还是空值,调用静态函数getBean就会报beanFactory为空。解决办法就是用DependsOn:

@DependsOn("app")
@Component
public class B implements InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        RestTemplate restTemplate = App.getBean(RestTemplate.class);
        System.out.println(restTemplate);
    }
}

@Autowired , @Qualifier ,@Resource

下面可以把项目中所有RestTemplate 实例都注入进来:

  @Autowired
  private List<RestTemplate> restTemplates = Collections.emptyList(); 

@Autowired(required = false)

当不能确定 Spring 容器中一定拥有某个类的 Bean 时,可以在需要自动注入该类 Bean 的地方可以使用 @Autowired(required = false) ,这等于告诉 Spring:在找不到匹配 Bean 时也不报错。

当然,一般情况下,使用 @Autowired 的地方都是需要注入 Bean 的,使用了自动注入而又允许不注入的情况一般仅会在开发期或测试期碰到(如为了快速启动 Spring 容器,仅引入一些模块的 Spring 配置文件),所以 @Autowired(required = false) 会很少用到。

@Qualifier

使用@Autowired注释进行byType注入,如果需要byName(byName就是通过id去标识)注入,增加@Qualifier注释。一般在候选Bean数目不为1时应该加@Qualifier注释。

在默认情况下使用 @Autowired 注释进行自动注入时,Spring 容器中匹配的候选 Bean 数目必须有且仅有一个。当找不到一个匹配的 Bean 时,Spring 容器将抛出

BeanCreationException 异常,并指出必须至少拥有一个匹配的 Bean。

和找不到一个类型匹配 Bean 相反的一个错误是:如果 Spring 容器中拥有多个候选 Bean,Spring 容器在启动时也会抛出 BeanCreationException 异常。

Spring 允许我们通过 @Qualifier 注释指定注入 Bean 的名称,这样歧义就消除了,可以通过下面的方法解决异常:

@Autowired   
@Qualifier("office")   
private Office office;  

//@Qualifier(“office”)中的office是Bean的名称,所以@Autowired和@Qualifier结合使用时,
//自动注入的策略就从byType转变成byName了

@Resource

Spring不但支持自己定义的@Autowired注解,还支持几个由JSR-250规范定义的注解,它们分别是@Resource、@PostConstruct以及@PreDestroy。

@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入罢了。@Resource有两个属性是比较重要的,分是name和type,Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。

@Resource装配顺序

  • 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
  • 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
  • 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
  • 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;

@Component、@Repository、@Service、@Controller

  • @Service用于标注业务层组件
  • @Controller用于标注控制层组件(如struts中的action)
  • @Repository用于标注数据访问组件,即DAO组件
  • @Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。


@Import

Import 注解可以使普通类导入到 IoC容器中。

@Configuration
// 这里会把普通A类加载到spring
@Import({ A.class })
public class MainConfig {
}

想要让一个普通类接受 Spring 容器管理,有以下方法:

  • 使用 @Bean 注解。
  • 使用 @Controller @Service @Repository @Component 注解标注该类,然后再使用 @ComponentScan 扫描包。
  • @Import 方法,即现在这种方式。

Import注解 的重要用法( 指定Selector 动态加载bean):

//自定义逻辑返回需要导入的组件
public class MyImportSelector implements ImportSelector {
	// 返回值,就是到导入到容器中的组件全类名
	// AnnotationMetadata:当前标注@Import注解的类的所有注解信息
	@Override
	public String[] selectImports(AnnotationMetadata importingClassMetadata) {
		// 方法不要返回null值
                // 这里作一些动态逻辑 加载不同的bean
		return new String[] { "com.hadluo.B", "com.hadluo.A" };
	}
}

@Configuration
@Import({ MyImportSelector.class })
public class MainConfig {
}

Import注解其实是很强大的,mybatis的扫描mapper接口都是通过它来的。

下面有个Import注解使用的案例:

罗政:Mybatis Mapper接口扫描 大揭秘


@Conditional

指定一个match逻辑,返回true的话就注册当前作用的bean,否则就不注册bean。这个注解也是很有用,下面也是有一个使用案例:

罗政:Conditional注解线上案例 - 根据环境指定日志输出


SpringBoot内置了 许多Conditional , 非常好用:

  • ConditionalOnBean : 容器中注入过bean时,才加载当前bean。
  • ConditionalOnMissingBean : 容器中没有注入过bean时,才加载当前bean。
  • ConditionalOnClass : classpath下存在指定类时进行Bean装载。
  • ConditionalOnMissingClass : classpath下不存在指定类时进行Bean装载。
  • ConditionalOnJava : 只有运行指定版本的Java才会加载Bean。
  • ConditionalOnProperty : 系统中指定的对应的属性是否有对应的值。
  • ConditionalOnResource : 要加载的Bean依赖指定资源是否存在于classpath中。


@PropertySource

@PropertySource用来来提供属性文件的名称和位置,导入属性文件。之后就可以用@Value注解去引用:

@Configuration
@PropertySource("classpath:/com/dev/javatechonline/app.properties")
public class MyClass {
}

导入多个属性文件:

@Configuration 
@PropertySources({ 
              @PropertySource("classpath:/com/dev/javatechonline/app1.properties"), 
              @PropertySource("classpath:/com/dev/javatechonline/app2.properties") 
})
public class MyClass { }

@Value

@Value是开发过程中使用比较频繁的注解之一,它的作用是将配置文件中key对应的值赋值给它标注的属性。

用分号指定默认值:

@Value("${abc:123}")
String g ;

指定自定义属性文件:

@PropertySource({"classpath:abc.properties"})
public class Abc{
    @Value("${abc:123}")
    String g ;
}

/////////g  abc.properties文件 key为abc 配置的值没有配置的话就是123

#{…}的用法:

// SpEL:调用字符串Hello World的concat方法
@Value("#{'Hello World'.concat('!')}")
private String helloWorld;

// SpEL: 调用字符串的getBytes方法,然后调用length属性
@Value("#{'Hello World'.bytes.length}")
private String helloWorldbytes;

@ConfigurationProperties

该注解有一个prefix属性,通过指定的前缀,绑定配置文件中的配置,该注解可以放在类上,也可以放在方法上。比较常见的就是配置读写分离的场景。

配置文件内容 #

https://www.cnblogs.com/tian874540961/p/12146467.html#3156962576

#数据源
spring.datasource.druid.write.url=jdbc:mysql://localhost:3306/jpa
spring.datasource.druid.write.username=root
spring.datasource.druid.write.password=1
spring.datasource.druid.write.driver-class-name=com.mysql.jdbc.Driver

spring.datasource.druid.read.url=jdbc:mysql://localhost:3306/jpa
spring.datasource.druid.read.username=root
spring.datasource.druid.read.password=1
spring.datasource.druid.read.driver-class-name=com.mysql.jdbc.Driver

java代码

prfix=spring.datasource.druid.read 就会找spring.datasource.druid.read这个前缀的配置,自动给DruidDataSource里面的url,username,password等赋值为配置里面的值,注意,字段必须要对应(java类和配置字段)。

http://prfix%3Dspring.datasource.druid.read/

@Configuration
public class DruidDataSourceConfig {
    /**
     * DataSource 配置
     * @return
     */
    @ConfigurationProperties(prefix = "spring.datasource.druid.read")
    @Bean(name = "readDruidDataSource")
    public DataSource readDruidDataSource() {
        return new DruidDataSource();
    }


    /**
     * DataSource 配置
     * @return
     */
    @ConfigurationProperties(prefix = "spring.datasource.druid.write")
    @Bean(name = "writeDruidDataSource")
    @Primary
    public DataSource writeDruidDataSource() {
        return new DruidDataSource();
    }
}

也许有的人看到这里会比较疑惑,prefix并没有指定配置的全限定名,那它是怎么进行配置绑定的呢?

相信大家肯定了解@Value注解,它可以通过全限定名进行配置的绑定,这里的ConfigurationProperties其实就类似于使用多个@Value同时绑定,绑定的对象就是DataSource类型的对象,而且是 隐式绑定 的,意味着在配置文件编写的时候需要与对应类的字段名称 相同 ,比如上述 spring.datasource.druid.write.url=jdbc:mysql://localhost:3306/jpa ,当然了,你也可以随便写个配置,比如 spring.datasource.druid.write.uuu=www.baidu.com ,此时你只需要在注解中加上以下参数即可

ignoreUnknownFields = false 告诉Spring Boot在有属性不能匹配到声明的域的时候抛出异常。

推荐一个Java架构师博客,带你一起写架构:

Java架构师修炼

支付宝打赏 微信打赏

如果文章对您有帮助,您可以鼓励一下作者