Spring的控制反转和依赖注入

IoC(Inversion of Control):控制反转
是指程序中对象的获取方式发生反转,由最初的构造器方式创建转变为由第三方框架创建、注入。                                                                        
对象的创建权,反转到 Spring 容器:由容器根据配置文件去创建实例并维护各个实例间的依赖关系。
深入理解:可以把IoC看作是工厂模式的升华,可以把IoC看作是一个大工厂,只不过这个大工厂里要生成的对象都是在XML文件给出的定义的,然后利用Java的"反射"编程,根据XML中给出的类名和类型生成相应的对象。
反射:通俗说就是根据给出的类名来生成对象。这种编程方式可以让对象在生成时才决定要生成哪一种对象。

DI(Dependency Injection)—IoC的另一种表述方式
即组件以一些预先定义好的方式(例如setter方法)接受来自容器的资源注入。
说白了就是Spring 创建对象的过程中,将对象依赖属性通过配置进行注入。相对于IoC而言,这种表述更直接。
IoC是一种思想,而DI是实现IoC的主要技术途径。

依赖注入的方式:                                                                                                                                                                                              
①setter注入(通常也叫属性注入) --------------------------------------------------------------------
即通过set方法注入bean的属性值和依赖的对象,这种方式需要有被注入属性的set方法。
先创建一个实体类UserService,定义两个成员变量name和age,及其set方法。然后就可以在配置文件中使用属性注入:

<bean id="emp" class="mypack.entity.Emp">
      		<property name="id" value="11"></property>
      		<property name="name" value="lbj"></property>
      		<property name="age" value="21"></property>
      		<property name="salary" value="5000"></property>
      </bean>

②构造函数注入 --------------------------------------------------------------------
通过构造方法注入bean的属性值或依赖的对象,它保证了bean实例在实例化后就可以使用。这种写法是用于某个类里面的构造方法的参数为其他类的时候。
例如在EmpDao类的构造方法中,参数为Emp类型,但是我没有为其创建set方法,所以就不能支持setter注入。

<bean id="empDao" class="mypack.dao.EmpDao">
      		<constructor-arg ref="emp"></constructor-arg>
      </bean>
<bean id="car">
    <constructor-arg value="Audi"/>
    <constructor-arg value="BWM"/>
</bean>

Spring的自动装配
Spring IoC容器可以自动装配(autowire)相互协作bean之间的关联关系,autowire可以针对单个bean进行设置,它的方便之处在于减少XML的注入配置。在XML文件中,可以在元素中声明autowire属性。

①byName ---------------------------------------------------------------------------------------------
IoC容器会根据set方法中对应的属性名字找到对应的JavaBean的id。所以必须将目标bean的id和属性名设置完全相同。

②byType -----------------------------------------------------------------------------------------------
IoC容器会根据set方法中参数的类型找到对应的JavaBean,也就是说set方法的参数类型要与bean的class类型一致,才能匹配到。

以上两种方法本质上都是通过反射构造出对应的set方法,然后执行set方法。

③constructor ---------------------------------------------------------------------------------------------
IoC容器会根据有参构造器中参数类型找到对应的JavaBean。
当bean中存在多个构造器时,此种方式将会很复杂,故不推荐使用。

④autodetect -----------------------------------------------------------------------------------------------
先通过constructor,若没有匹配到再通过byType匹配。


以上学到的bean的配置都是基于XML的方式,接下来学习基于注解的方式配置bean。


组件扫描(component scanning)

Spring能够从classpath下自动扫描、侦测和实例化具有特定注解的组件。
使用组件扫描,首先需要指定扫描类路径:                                                                                                                                                           
<context:component-scan base-package="com.springdemo"></context:component-scan>
特定组件包括:
@Component:基本注解,标识了一个受Spring管理的组件
@Repository:标识持久层组件
@Service:标识业务层组件
@Controller:标识控制层组件

对于扫描到的组件,Spring也有默认的命名策略:
使用非限定类名,第一个字母小写,作为默认的id值,例如UserService类的默认bean的id值是"userService"。
我们也可以在注解标记中自定义id,例如:@Component("userService1")。

指定组件的作用域 ---------------------------------------------------------------------------------------------
通常受Spring管理的组件,默认作用域是singleton,我们可以使用@Scope注解指定作用域,例如:@Scope("prototype")

初始化回调和销毁回调注解 -----------------------------------------------------------------------------------
@PostConstruct和@PreDestroy分别对应初始化回调和销毁回调。

基于注解注入bean的属性

元素还会自动注册AutowiredAnnotationBeanPostProcessor实例,该实例可自动装配具有 @Autowired、@Resource和@Inject注解的属性

①@Resource ---------------------------------------------------------------------------------------------

可以用在字段或属性的set方法上面,默认按照byName自动注入。

@Resource注解有两个属性比较重要,分别是name和type,name属性解析为bean的名字,而type属性则解析为bean的类型。如果使用name属性,则按byName自动注入,而使用type属性,则按byType自动注入。

@Resource默认按byName装配。名称可以通过name属性来指定,如@Resource(name="userDao"),如果没有指定name属性,当注解标记在字段上,则取字段名称作为bean名称寻找依赖对象,当注解标注在属性的set方法上,则默认按属性名作为bean名称寻找依赖对象。

注意:如果没有指定name属性,并且按照默认的名称仍找不到依赖对象,@Resource会会退到按类型装配。但一旦指定了name属性,就只能按名称装配了。

②@Autowired   ---------------------------------------------------------------------------------------------

自动装配具有兼容类型的单个bean属性,即按照byType自动注入。
可应用于构造器、字段和set方法上面。
默认情况下,要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:@Autowired(required=false)。
默认情况下,当IoC容器里存在多个类型兼容(如一个接口下有多个实现类)的bean时,通过类型的自动装配将无法工作,此时可以结合@Qualifier注解按名称装配。
@Qualifier的意思是合格者,通过这个标识表明了哪个实现类才是我们需要的。
@Qualifier可以标注在@Autowire注解下面,也可以对方法的入参标注。
例如:public void setUser(@Qualifier("service") User user){……}

猜你喜欢

转载自blog.csdn.net/qq_33800083/article/details/80166156