Spring学习总结(2)-自动装配
上面说过,IOC的注入有两个地方需要提供依赖关系,一是类的定义中,二是在spring的配置中需要去描述。自动装配则把第二个取消了,即我们仅仅需要在类中提供依赖,继而把对象交给容器管理即可完成注入。在实际开发中,描述类之间的依赖关系通常是大篇幅的,如果使用自动装配则省去了很多配置,并且如果对象的依赖发生更新我们可以不需要去更新配置,但是也带来了一定的缺点。
说白了就是只需要声明bean,至于对象间的相互引用关系由Spring自己搞定。。
使用方式:no(不启用),byName(根据名称),byType(根据类型),constructor(构造方法)
<beans .... default-autowire="byType"> </beans>
自动装配的优点参考文档:https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-autowire
缺点参考文档:https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-autowired-exceptions
byType的装配过程:Spring第一步会把所有的bean都加载到容器中,第二步解析时发现Service里有个dao依赖,就会按照依赖去找类属性是这个Dao或者父类是这个Dao的类属性进行注入。
如果同一个接口有2个实现类,并且还使用接口注入的话就会报错,这是需要改为byName方式,或者根据实现类注入。
另外,在bean标签中是可以单独指定装配方式的:
<bean id="ClassOne" class="****" autowired="byType">
annotation注入方式中的自动装配:
使用注解@Autowired默认是使用的转配方式是byType,如果没有找到还会使用byName,还没有找到要装配的类,报错。
注解@Resource默认使用byName,根据属性名来确认的,还可以通过type来指定具体的名称,如 @Resource(type = “IndexImpl”)
spring懒加载
在Spring配置文件里增加如下语句,表示Spring并不是在在项目启动时全部注入,而是在使用时才会注入,默认false
<beans .....
default-lazy-init="true"> </beans>
SpringBean的作用域
singleton:单例
prototype:标准,每次都是新的对象
request:限定每个Http请求都是新的对象
session:将单个bean定义的范围限定为HTTP会话的生命周期。仅在可感知web的Spring ApplicationContext上下文中有效。
applicaiton:将单个bean定义的范围限定为ServletContext的生命周期。仅在可感知web的Spring ApplicationContext上下文中有效。
websocket:将单个bean定义的范围限定为WebSocket的生命周期。仅在可感知web的Spring ApplicationContext上下文中有效。
@Autowired注解
@Autowired注解到底使用了那种方式自动装配技术的呢?从Spring源码可以看到,Spring是使用后置处理器AutowiredAnnotationBeanPostProcessor来实现@Autowired的自动装配的,代码如下:
这里个beanFactory是ConfigurableListableBeanFactory接口,而实现这个接口的类是DefaultListableBeanFactory,在DefaultListableBeanFactory类中的方法resolveDependency又调用了方法doResolveDependency
通过这段代码,我们可以确定,@Autowired代码是首先是根据byType查找对象,如果查到的对象的数量大于1,再根据byName查找的。
注意:
1、在@Controller/@Service等容器中,默认情况下,scope值是单例-singleton的,也是线程不安全的。
2、尽量不要在@Controller/@Service等容器中定义静态变量,不论是单例(singleton)还是多实例(prototype)他都是线程不安全的。
3、默认注入的Bean对象,在不设置scope的时候他也是线程不安全的。
4、一定要定义变量的话,用ThreadLocal来封装,这个是线程安全的