在前面介绍过@Controller的用法了,它可以接供一个api接口。那么除此之外,还有哪些是常用注解呢?下面介绍几个我个人认为常用的。@Bean @Autowired @Resources @Component、@Service、@Controler、@Repository、@Configuration
一、@SpringBootApplication注解
Application启动类中,会有该注解,先看代码:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
通过源码查看,我们可以又包含了一组注解,核心的有三个注解:
换句话说,我们把这个注解换成这三个类,也可以实现启动类。
//@SpringBootApplication
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
二、@SpringBootConfiguration和@Configuration
1、@SpringBootConfiguration继承自@Configuration,二者功能相似,标注当前类是配置类
@SpringBootConfiguration就是一个特殊的@Configuration注解,一般专门用在main方法的类上。
2、@Configuration,标注当前类是配置类,向Spring容器注入组件。
底层是含有@Component ,所以@Configuration 具有和 @Component 的作用。因此context:component-scan/或者@ComponentScan都能处理@Configuration注解的类。
三、@Bean 和@Componet
1、配置类里面使用@Bean标注在方法上给IoC容器注册组件,默认也是单实例的。
使用@Bean注解标注的方法,返回的类型都会直接注册为bean。
2、@Component和@Bean都是向spring容器注册组件,区别在于,Component作用于类上,@Bean作用于方法上。@Component 通常是通过路径扫描来自动侦测以及自动装配到 Spring 容器中,比如@SpringBootConfiguration包含了@ComponentScan注解,它就会自动扫描所有标注了@Component的类并自动装配到 Spring 容器中。
3、单例?IoC容器注册组件?有什么意义或作用吗?
我们举一个例子,我们建立一个普通类App,我们通过new App()可以使用,好像加不加@Componet或@Bean没有关系。下面,我们在App的构造方法加一个print命令:
public class App {
private String name;
private String description;
public App(){
System.out.println("App 构造方法:");
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
@RestController
@RequestMapping("/annotate")
public class Annotate {
@GetMapping("/bean")
public String bean(){
App app=new App();
app.setName("aa");
System.out.println("app:"+app.getName());
return "OK";
}
}
然后,我们刷新网页,并多刷几次,就会发现,每调用一次接口,App构造方法都是执行一次。
我们试一下@Componet注解,在类上面添加。
@Component
public class App {
private String name;
private String description;
public App(){
System.out.println("App 构造方法:");
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
然后,在调用的地方使用@Resource或@Autowired调用:
@RestController
@RequestMapping("/annotate")
public class Annotate {
@Resource
App app;
@GetMapping("/bean")
public String bean(){
app.setName("aa");
System.out.println("app:"+app.getName());
return "OK";
}
}
然后,我们再次刷新网页,无论刷多少次,App构造方法只会执行一次:
简单总结一下:通过@Bean@Componet注入到Spring容器的组件,会交由Spring管理,只会初始化一次。这样有很多好处,比如各种配置信息都是全局,并不需要重复加载。所以全局配置应该尽可能多的通过配置类注册到Spring容器。
四、@Autowired和@Resource
上面App类通过@Componet注入时,我们在使用的地方是通过@Resource实现自动装配的。
重点:与Spring容器发生关系!
SpringBoot启动时,会构建一个SpringApplication的实例,然后调用这个实例的run方法。在这个run方法里面,会构造Spring容器(ApplicationContext)上下文。
所以,所有注入到容器的组件,都在SpringApplication.run执行时加载。由于是单例模式,所以后面再引用时就不需要构建了,直接返回组件使用。
1、@Autowired和@Resource注解都是作为bean对象注入的时候使用的
@Autowired注解是Spring提供的,而@Resource注解是J2EE本身提供的
2、@Autowird注解默认通过byType方式注入,而@Resource注解默认通过byName方式注入
@Autowire + @qualifier("") = @Resource(name="")
五、@Service与@Repository
@ Repository,@ Service和@Controller可以理解为特殊的@Component。更适合于通过工具进行处理或与其方面相关联。都入注入Spring容器。
@Controller较早前有介绍,会在Spring启动时注入容器,对外暴露接口,是控制层。
@Service :业务逻辑层,即与数据相关的计算和服务。它将根据需要调用@Repository层。
@Repository :这是应用程序的持久层(数据访问层),用于从数据库中获取数据。 即所有与数据库有关的操作都由该层完成。
@Repository会捕获特定于平台的异常,并将它们作为Spring统一的未经检查的异常之一重新抛出。
五、总结
Spring启动时,构建了一个实例,这个实例构建了一个容器。然后,大家就可以把需要共享的内容放到这个容器里。放进去的东西有一个统一的规范叫javaBean,@Bean表示。放去的方法是固定的,所以提供了@Configuration\@Componet以及他们派生出来的@ Repository、@ Service和@Controller。那@Autowired和@Resource就是一个取出来的方式,取javaBean出来时用名字也行,但为了防止同名,有的也用身份证号码,所以就出现了两个不同的方式。
然后,即然这个容器是实例构建的,所以如果离开了这个实例,是获取不到这个容器内的javaBean的。
啥?为啥会出现离开这个容器的情况,比如我们在main中run以外的地方想引用容器内的东西就不行了。再比如一些配置类的加载都是依赖于这个实例的,即SpringApplication。
当然,也不是完全没有办法,可以用一个变量接收它,然后就可以获取这个容器里的Bean对象以及其他东西了。
@SpringBootApplication
public class Application {
public static ConfigurableApplicationContext ac;
public static void main(String[] args) {
ac= SpringApplication.run(Application.class, args);
System.out.println(ac.getBean("app"));
}
}