容器功能及组件添加(也叫注解)
注解 | 说明 |
---|---|
@Configuration | |
@Bean |
1、@Configuration与@Bean
项目概览
代码如下:
(1)MyBean类
package myProject.bean;
public class MyBean {
public MyBean(){
System.out.println("This is construction method of MyBean");
}
public void initMyBean(){
System.out.println("This is initialization method of MyBean ");
}
}
(2)MyConfiguration类
package myProject.config;
import myProject.bean.MyBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
*@Configuration:现在大部分的项目都采用了基于注解的配置,使
*用@Configuration标记类作为配置类替换XML文件。表明在一个类
*中可以声明一个或多个@bean标记的方法,这些方法被spring容器管
*理。
*/
@Configuration//表明这是一个配置类
public class MyConfiguration {
/**有一个myBean01()的方法并用@Bean 进行注释,返回一个
*MyBean()的实例,表明这个方法是需要被Spring进行管理
*的bean。@Bean 如果不指定名称的话,默认使用myBean名
*称,也就是小写的名称。
*/
@Bean
public MyBean myBean01(){
System.out.println("generate MyBean instance");
return new MyBean();
}
}
(3)启动@Configuration 注解的类
查看启动@Configuration注解类介绍
大概意思师说@Configuration配置类典型的通过使用AnnotationConfigApplicationContext或者AnnotationConfigWebApplicationContext启动。
用AnnotationConfigApplicationContext启动看看:
package myProject.mainApplication;
import myProject.config.MyConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =new AnnotationConfigApplicationContext();
context.register(MyConfiguration.class);
context.refresh();
}
}
运行结果:
延展:
- @Configuration中的proxyBeanMethods属性
- 首先引出两个概念:Full全模式与Lite轻量级模式
- Full全模式:@Configuration(proxyBeanMethods=true),将proxyBeanMethods属性设置为true时即为Full全模式。
- 特点:在该模式下注入容器中的同一组件无论被取出多少次都是同一个bean实例,即单实例对象。且在该模式下SpringBoot每次启动都会判断检查容器中是否存在该组件
- Lite轻量级模式:@Configuration(proxyBeanMethods=false)
- 特点:在该模式下注入容器的同一个组件无论被取出多少次都是不同的bean实例,即多实例对象,在该模式下SpringBoot每次启动都会跳过检查容器中是否存在该组件。
- 什么时候用Full全模式,什么时候用Lite轻量级模式?
- 当在你的同一个Configuration配置类中,注入到容器中的bean实例之间有依赖关系时,建议使用Full全模式;没有依赖关系时建议使用Lite轻量级模式,以提高springboot的启动速度。
- 实操
项目概览
新建一个Boy和一个girl类
package myproject_proxybeanmethods.bean;
public class Boy {
private String name;
private Integer age;
public Boy(String name,Integer age){
this.name=name;
this.age=age;
}
public void setName(String name){
this.name=name;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getAge() {
return age;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Boy{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package myproject_proxybeanmethods.bean;
public class Girl {
private String name;
private Integer age;
private Boy boyFriend;
// public Girl(String name,Integer age,Boy boyFriend){
// this.name=name;
// this.age=age;
// this.boyFriend=boyFriend;
// }
public void setName(String name){
this.name=name;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getAge() {
return age;
}
public String getName() {
return name;
}
public Boy getBoyFriend() {
return boyFriend;
}
public void setBoyFriend(Boy boy) {
this.boyFriend = boy;
}
@Override
public String toString() {
return "Girl{" +
"name='" + name + '\'' +
", age=" + age +
", boyFriend=" + boyFriend +
'}';
}
}
新建一个MyConfiguration类
package myproject_proxybeanmethods.myConfig;
import myproject_proxybeanmethods.bean.Boy;
import myproject_proxybeanmethods.bean.Girl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)//配置类
public class MyConfiguration {
@Bean//注册组件
public Boy getBoy(){
return new Boy("LiHua",18);
}
@Bean
public Girl getGirl(){
Girl girl=new Girl();
girl.setName("SuSan");
girl.setAge(17);
girl.setBoyFriend(getBoy());
return girl;
}
}
编写主方法
package myproject_proxybeanmethods.main;
import myproject_proxybeanmethods.bean.Boy;
import myproject_proxybeanmethods.bean.Girl;
import myproject_proxybeanmethods.myConfig.MyConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication(scanBasePackages="myproject_proxybeanmethods")
public class MyApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run= SpringApplication.run(MyApplication.class,args);
//获取组件
String[] names=run.getBeanDefinitionNames();
for (String name:names){
System.out.println("组件:"+name);
}
//配置类本身也是组件
MyConfiguration bean =run.getBean(MyConfiguration.class);
System.out.println("配置类也是组件:"+bean);
Boy boy1= bean.getBoy();
Boy boy2= bean.getBoy();
// Boy boy1=run.getBean("getBoy",Boy.class);
// Boy boy2= run.getBean("getBoy",Boy.class);
System.out.println("boy1==boy2?"+(boy1==boy2));
Boy boy=bean.getBoy();
Girl girl=bean.getGirl();
System.out.println("两个boyfirend相同吗?"+(boy==girl.getBoyFriend()));
}
}
若proxyBeanMethods==true,为单实例对象
若proxyBeanMethods==false,为多实例对象
@Configuration 使用@Component 进行原注解,因此被@Configuration 注解的类也可以被组件扫描到。
- 区分下@Controller, @Service, @Repository, @Component这四个注解:
- @Configuration 使用@Component 进行原注解,因此被@Configuration 注解的类也可以被组件扫描到。
- @Controller: 表明一个注解的类是一个"Controller",也就是控制器,可以把它理解为MVC 模式的Controller 这个角色。这个注解是一个特殊的@Component,允许实现类通过类路径的扫描扫描到。它通常与@RequestMapping 注解一起使用。
- @Service: 表明这个带注解的类是一个"Service",也就是服务层,可以把它理解为MVC 模式中的Service层这个角色,这个注解也是一个特殊的@Component,允许实现类通过类路径的扫描扫描到
- @Repository: 表明这个注解的类是一个"Repository",团队实现了JavaEE 模式中像是作为"Data Access Object" 可能作为DAO来使用,当与 PersistenceExceptionTranslationPostProcessor 结合使用时,这样注释的类有资格获得Spring转换的目的。这个注解也是@Component 的一个特殊实现,允许实现类能够被自动扫描到
- @Component: 表明这个注释的类是一个组件,当使用基于注释的配置和类路径扫描时,这些类被视为自动检测的候选者。
- 也就是说,上面四个注解标记的类都能够通过@ComponentScan 扫描到,上面四个注解最大的区别就是使用的场景和语义不一样,比如你定义一个Service类想要被Spring进行管理,你应该把它定义为@Service 而不是@Controller因为我们从语义上讲,@Service更像是一个服务的类,而不是一个控制器的类,@Component通常被称作组件,它可以标注任何你没有严格予以说明的类,比如说是一个配置类,它不属于MVC模式的任何一层,这个时候你更习惯于把它定义为 @Component。@Controller,@Service,@Repository 的注解上都有@Component,所以这三个注解都可以用@Component进行替换。