Spring 核心系列之 Bean 的注入
Hello,大家好,上两篇博文给大家分享了 Spring 容器的创建,以及 Bean 的生命周期,今天这一篇给大家讲解 Bean 的注入,就是 Bean 的一些注入方式,配置方式,然后再讲一下作者的一点使用经验,其实这一篇也是比较基础的东西,好了,老套路,文章结构:
基于 XML 的配置
基于注解的配置
基于 Spring config 的配置
几种配置方式的混合使用
1. 基于 XML 的配置
单单这一小节,如果往细了说,一篇博文都是不够的,因为知识点比较多,比较杂,而且,绝大部分都是一辈子用不上的.所以我想了想,还是直接干脆直接的上重点,很多不用的能提就提一下.
1.1 DTD 格式
Spring 的 XML 配置文件是 DTD 格式的,很多人其实对这个 XML 的开头一些配置都不理,我这里还是提一下:
Beans 标签的格式:
<Beans xmlns 属性 xmlns 属性 ... xsi 属性>
xmlns 属性定义命名空间,命名空间就是所有文件定义 bean 时带的前缀,像 aop:config, 这个标签的 aop 就是 aop 命名空间 ,没有加命名空间,就是默认的命名空间.
xsi 属性是根据全限定名称指定格式文件 xsd 的.
xmlns 属性的格式: xmlns: 命名空间 ="命名空间的全限定名 (可以随意命名, 命为 123 都可以)"
xsd 格式: "xmlns 定义的命名空间"+"空格"+"xsd 文件"
说下指定 xsd 的作用: 当你敲下 的前半段
1.2 定义 Bean
在 xml 文件里定义 Bean,贼简单的一个:
<bean id="stu" class="com.zdy.Student" >
<property name="name"><value>张三</value></property>
</bean>
是根据 setter 方法注入的.大家不要在看什么根据构造函数注入属性了.西坝,博主这么多年都没有过这种操作.都是根据 setter 注入的. 然后说一下,XML 里面有一些特殊字符,要使用转义序列代替,我给个表格:
至于网上说的还有一种: 的搞法,大家忽略掉.一是不方便,二是不支持 p 命名空间.待会会说到 p 命名空间.
上面的例子是注入的常量, 然后提下 bean 之间的相互依赖:
其他的一些什么集合注入,级联注入,我就不提了,根本没地用.
<bean id="car" calss="..." />
<bean id="boss" class="..." >
<property name="car">
<ref bean="car"></ref>
</property>
</bean>
1.3 xml 简化配置之 p 命名空间
上面的配置大家可以看到,贼复杂,而且在配置 bean 之间的相互依赖关系时还要使用 ref 标签.现在来给大家说下简化配置方式,和自动注入. p 命名空间是 Spring2.5 之后提供的,目的就是为了简化配置,看下效果:
<property name="name"><value>张三</value></property>
//使用前
< bean id = "stu"class = "com.zdy.Student" >
然后说下格式:
</bean>
//使用后
<bran id="stu" class="..." p:name="张三" />
对于字面常量: p: 属性名 =".."
对于引用 bean 的属性: p: 属性名 - ref="..."
然后提一下自动注入: 大家可以看到如果使用 ref 标签来注入 bean 依赖,程序员会死掉的.比如一个 Controller 层的 Bean, 依赖的 Service 层的 Bean 可能有 10 几个.一个个的配置了写.肯定是不行的.所以自动注入就出来了.@Autowired 注解,后面会讲.这里只是提一下.
然后提一下,标签,用于导入多个 xml 配置文件到一个 xml 配置文件中.
2. 基于注解的配置
上面可以看到,想把 Bean 注入到 Spring 容器中,可以使用标签,然后注入一些属性什么的.并且 bean 之间的引用关系可以使用 ref 标签.其实工作中这种操作基本没有公司会采纳的.因为太麻烦了,由于是配到 ref 标签时,真的会死人的.工作中,对于我们自己创建的 bean,肯定是会使用注解的方式来配置的, 具体使用方法:
在 xml 文件中或者 Java config 类中加上扫描路径,这里说下 xml 的配置:
<context:component-scan base-package="...">
我们自己写的 bean 上面加上 @Component,@Controller,@Service,@Dao
这样,我们的 UserDao 就注入到了 Spring 容器中.那么这种配置方式是如何解决相互依赖关系呢?@AutoWired
@Component
public class UerDao {
...
}
@Autoired 会自动根据类型来把 Bean 注入进来.这多简单呢?至于一些其他的参数,我就不扩展了.
@Controller
public class UserController{
@Autoired
private UserService userService;
...
}
3. 基于 Spring config 的配置
直接给一个 Config 类:
@Configuration 内部包含了 @Component,说白了,当这个 Bean 加入到 Spring 容器中时,它内部标注了 @Bean 的方法返回的 Bean 都会放到 Spring 容器中. 具体的语法我不多说了. @Configuration 类想加入到 Spring 容器中有三种方式,一种是在 xml 里通过 <context:component-scan base-package="..."> 扫描.一种是通过其他的 Config 类加上 @Componentscan 注解, 作用是一样的,扫描配置路径下的 POJO ,最后一种是在创建容器的时候直接指定这个 config 类,而不是 xml 配置文件,前面的博客讲到过.
@Configuration
public class UserJedisConfig {
@Bean
public CacheManager cacheManager(final RedisTemplate redisTemplate) {
return new RedisCacheManager(redisTemplate);
}
@Bean
public RedisTemplate<String, Object> redisTemplate2(final RedisConnectionFactory factory) {
final RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new RedisObjectSerializer());
template.afterPropertiesSet();
return template;
}
}
4. 几种配置方式的混合使用
好了,其实想把 Bean 加入到 Spring 容器中的方法无非是以上三种.而且也都很基础.我说下实际工作当中的一些小经验:
注解大于 xml 配置.大家自己也可以感觉到注解的方便.
自己写的 bean 全部使用注解来注入到容器中.至于容器启动的时候是使用 xml 文件还是 Config 类,这都无所谓.只要加了自动扫描即可.
集成一些三方的框架 (如 Jedis),需要放入三方的 bean 到 Spring 容器中时,这时候没办法使用注解,可以使用 xml 文件配置或者 config 类配置.
最后给一个比较图,和使用场景图:
最后说一下,作者遇到过的实际的这几种方式的选择:
之前在某家房地产公司用到的是 "XML + 注解",这种方式还是比较多见,比较传统的.web 项目,容器启动以来一个 xml 文件,然后 xml 文件中配置扫描的跟路径,自己写的 Bean 放在路径下面并加上类似于 @Componenet 的注解,依赖关系依赖于 @Autowired 注解.如果引用了一些三方的框架,想使用一些框架自带的 Bean,就在 xml 中配置标签加到容器里面去.这是比较传统的 Spring 容器使用方式.
Spring boot,用过或者了解过 Spring boot 的小伙伴应该知道,Spring boot 中是没有 xml 文件的,容器启用依赖一个自带的 config 类,这个 config 类会自动扫描跟路径之下的,所以我们开发的类只要加上了 @Component 类似的注解都会被加入到容器当中.依赖一些三方的框架的 Bean,一般情况下,Spring boot 会有一些 auto 注入机制,自动根据配置的参数创建 Bean 并自动注入 bean 到容器中.开发者直接 @Autowired 就可以使用.特殊情况下才会自己写一个 config 类来注入一下 Spring boot 没有自带的三方 bean.为什么用过 Spring boot 的小伙伴都觉得 Spring boot 比较简洁呢?你想一想,如果你要使用 Jedis,只需要 pom 引入即可.然后就直接 @Autowired 注入相应的 bean,根本不需要配置.这也是 Spring boot 最最核心的一个特色.后期有机会讲 Spring boot 时给大家分享这种自动注入是如何实现的.
结语
好了,其实这一小节比较简单,大家可以看到,作者没有讲具体太细的使用方法,像 @Autowired 的一些属性,@Configuration 的一些语法什么的,作者都是一笔带过,给了个例子,因为作者觉得这一篇的重点应该是把握好这几种注入 Bean 的机制,举几个例子:
开发者在自己的工程中看到了写的 bean 被加上了 @Component 注解,要能知道这个 bean 是怎么被加进来的 (是 xml 扫描,还是 config 文件扫描),
接到工程发现 web 工程竟然没有 Spring 的 XML 主文件.(这时候就要想到是不是通过 Config 类来启动的容器)
开发者想加入一些三方的 Bean 到容器里,是使用 xml 配置,还是使用 config 类配置. 好了,这一篇给大家分享完了,今天周一,大家鼓足干劲,好好上班,赚钱过年回家.Over,Hava a good day .
来源: https://juejin.im/post/5a530b4bf265da3e2f00cad3