挺感谢雷老师的spring boot1,spring boot2两个教程的。除了讲了spring boot版本带来的差异外,讲法也略有不同。我个人反正觉得spring boot2相对于1来讲更适合全览和概括。这里讲到的五个比较底层的注解,而且其在自动配置上起了很大的作用(不仅仅是spring boot的注解,而是spring的),这里详细介绍一下。
这里划重点一句话:只有在容器中的组件才可以拥有SpringBoot提供的各种强大的功能!!!!
@Configuration
这个注解是告诉springboot这是一个配置类,等同于以前spring的配置文件
它里面可以定义多个bean,相当于之前xml文件中的<bean>标签。
默认的这个@bean注解修饰的方法:方法名就是组件的id(这里也可以自己自定义bean中写想要的组件id)。方法的返回类型就是组件的类型,返回值的就是组件在容器中存在的实例。
下面是一个简单的demo:
-
在@Configuration修饰的类中注入两个bean
如上代码,sysDriver和sysUser就是两个普通的实体类,然后我在被@Configuration修饰的类中注入了两个bean分别是这个类型。为了测试出效果我特意一个用默认的方式,一个指定了组件id。
@Configuration
public class MyConfig {
@Bean
public SysDriver sysDriver() {
SysDriver sysDriver = new SysDriver();
sysDriver.setId(2);
sysDriver.setName("lisi");
sysDriver.setSex(1);
return sysDriver;
}
@Bean("user")
public SysUser sysUser() {
SysUser sysUser = new SysUser();
sysUser.setId(1);
sysUser.setName("lisijia");
sysUser.setAge(26);
return sysUser;
}
}
下面我们启动项目看看容器中是不是有这两个组件了:
其实到这我们就算测试成功了,连名称都和我们意料的一样,但是闲着也是闲着,我们可以继续看下容器中的实例是不是和我们放进去的一样:
事实证明这个和我们放进去的是一样的。所以说我们上面说的默认方法名称是id,返回类型是组件的类型,返回对象就是组件实例得到证实了!
而且这个组件应该是唯一的,也就是我获取几次得到的都应该是一个对象,下面我们再测试一下:
我这里用的==。也就是只有一个对象才会是true,所以说容器中获得的组件是单例的。
当然了,配置类本身也是组件。这个也很好理解。
重点来了,!!相对于Spring boot1.x。2.x有一个很明显的变化:在@Configuration中多了一个属性---代理bean方法:proxyBeanMethods,默认是true
这个属性的作用比较好理解:上面属性是代理bean方法。因为配置类本身就是一个类,所以理论上我们是可以通过这个配置类直接调用这个被@bean注释的方法。如下用法:
而当上面说的那个bean代理属性值是false的时候,那么外部访问调用的和组件里的就不是一个对象了。如下截图:
这里的逻辑是当myConfig的属性proxyBeanMethods是true。那么它本身已经被增强了,本身就是代理对象了,这样通过它访问的对象都会去容器中找是不是有这个组件,如果有就会返回这个组件,没有才生成新的。你是如果proxyBeanMethods属性是false那么他就是普通的组件了,外部访问的话会新生成实例。
这里有两个概念:full和lite。轻量级和重量级。首先full的话调用性能会很慢,因为每次调用都要先去组件中寻找是不是存在这个组件。而lite则不用,每次调用就直接new,不用检查。而这个功能适用于组件依赖:
比如config中有两个组件A,B。并且在A中调用了B。
如果设置proxyBeanMethods是true。那么A中的B会保持单例的,就是容器中的那个实例。否则A中的B不会是容器中的那个。
据说如果不存在组件依赖的情况我们大多数时候会把其设置为false,使得性能更好,但是存在组件依赖的时候还是要设置为true保证程序的正确性的。
@Import
这个也是给容器中添加组件,它的参数是个class数组,可以给容器中导入很多组件。给容器中自动创建出参数类型的组件。如下图:
很明显,这个import注解中的Test,Test1,Test2都自动纳入spring容器中了。而且默认组件的id就是全类名。
@Confitional
这个是条件装配,之前说过好多次了,这个是个基本注解,可以演变成好多注解。如下图:
其各种条件满足的条件都是字面上的意思,比如要有某个bean,要没有某个bean,要是web环境,要是存在某个类,要不存在某个类,反正见名知意,我觉得也没必要一一细说了,之前有一个带中文的图在spring boot1.x版本的记笔上,我也懒得再翻出去贴上了,一个个注解用多了就直到啥意思了。这个注解就这样了。
@ImportResource("/path")
类似于第二个注解@Import,只不过这个是导入某个配置文件中的组件(虽然我有点理解不了为什么先写到xml上再解析,不过可能维护老项目或者三方项目都会遇到吧)。如下demo:
我在配置文件中用xml配置了个组件,id是lsj。然后正常来讲这个配置文件是不会起作用的,但是我把这个@ImportResource(“/文件路径”)放在配置类上,这个配置文件就会起作用。
@ConfigurationProperties
这个其实其实就是配置绑定。指定前缀的配置属性会绑定到当前类的属性中。
然后想要给某个类绑定某些属性,只要指定前缀和属性名称,然后在类上先纳入spring管理(也就是放到容器中),然后用配置绑定这个注解@ConfigurationProperties绑定指定前缀就可以了(这里默认在application.properties/yml中找)
如下demo:
我把SysUser这个类纳入容器管理并且绑定配置文件中的user.bean前缀的属性。
所以user.bean.id绑定在了id上,同理user.bean.age绑定到age属性。user.bean.name绑定在name属性上。最终我输出容器中叫做wfs这个id的组件,结果是我们配置文件配置的内容。修改配置文件重启组件中值也会变化的。
而且我这里还遇到一个好玩的事,我本来想绑定在user.这个前缀上的,但是我发现user.name=xxx我怎么设置都不起作用,输出的值都是我笔记本上用户的名称。。。所以说一个合理的事实:user.name被别的东西绑定了已经,而且优先级高于我这个配置文件(关于配置文件的优先级我之前记过笔记,估计以后还会整理)。反正也算是一个小小的惊喜吧,然后这种方式配置绑定就这样了。
还有一种绑定是开启配置绑定功能并且将其自动注册到容器中。总而言之:
@EnableConfigurationProperties(开启自动绑定(找类上的那个@ConfigurationProperties注解生效,并且将类纳入容器))
@ConfigurationProperties
等价于
@Component(五大组件注解都可以)
@ConfigurationProperties
上面说了第二种实现,下面是第一种实现的demo:
有一点需要注意:这种方式虽然也纳入容器中了,但是bean的id是默认的,反正我是在所有的bean中找的。。规律应该是配置文件前缀-全类名。
感兴趣的可以自己试试。
到这里,这五个注解就讲完了,有的说的多点,有的说的少点,反正我个人感觉都是常用又实用的。这些都是看spring boot源码所必要的基本功。以后会常常遇到,如果暂时觉得记不住也问题不大,看一段时间源码都自然而然的记住啦!
本篇笔记就记到这里,如果稍微帮到你了记得点个喜欢点个关注,也祝大家工作顺顺利利!生活健健康康吧~!今日份毒鸡汤:除非付出行动,否则口说无凭,没有人能通过祈祷试图改变人生!