IOC

      对象间存在依赖关系。假如A组件调用了B组件的方法,就可以称A组件依赖于B组件。通过使用依赖注入,Java EE应用中的各种组件不需要以硬编码方式耦合在一起,甚至无需使用工厂模式。当某个Java 实例需要其他Java 实例时,系统自动提供所需要的实例,无需程序显示获取,这种自动提供java实例称之为依赖注入,也可以称之为控制反转(Inversion of Control IoC)。
      其实不管是控制反转还是依赖注入,都可以这样理解:当某个Java实例(调用者)需要另一个Java实例(被调用者)时,在传统的程序设计过程中,通常有调用者来创建被调用者的实例。但是在依赖注入/控制反转模式下,创建被调用者的工作不再是有调用者来完成,而是由Spring容器来完成,然后注入调用者。

Bean的实例化方式:
      默认情况下调用new ClassPathXmlApplicationContext("beans.xml")即容器启动时初始化bean,之后只有singleton。可在bean节点设置lazy-init="true",或在beans节点中设置default-lazy-init="true",对全部Bean都在getBean()时才初始化。
1.类构造器
<bean id="personServiceBean" class="com.zero.service.impl.PersonServiceBean">

2.静态工厂方法
public class PersonServiceBeanStaticFactory {
	public static PersonServiceBean create() {
		return new PersonServiceBean();
	}
}

<bean id="factory" class="com.zero.service.impl.PersonServiceBeanStaticFactory" factory-method="create"></bean>
3.实例工厂方法
public class PersonServiceBeanFactory {
	public PersonServiceBean create() {
		return new PersonServiceBean();
	}
}

<bean id="factoryBean" class="com.zero.service.impl.PersonServiceBeanFactory" ></bean>
<bean id="factory" factory-bean="factoryBean" factory-method="create"></bean>

Bean的init-method与destory-method
       可以让Spring容器在初始化Bean后执行init-method,在Spring容器关闭时执行destory-method方法
       <bean id="personServiceBean" class="com.zero.service.impl.PersonServiceBean" init-method="init" destroy-method="close"></bean>
        注意:使用BeanFactory的子类AbstractApplicationContext来完成close()方法,ApplicationContext无此方法。

依赖注入:
1、设置注入:IoC容器使用属性的setter方法来注入被依赖的实例。
2、构造注入:IoC容器使用构造器来注入被依赖的实例。
3、filed注入:注解方式

一、设置注入
设置注入是指IoC容器使用属性的setter方法来注入被依赖的实例。这种注入方式比较简单、直观。
public class Chinese implements Person {  
 private Axe axe;  
 private String name; 
 // 设值注入所需的setter方法  
 public void setAxe(Axe axe) {  
    this.axe = axe;  
 }  
 public void setName(String name) {  
     this.name = name;  
 }  
 // 实现Person接口的userAxe方法  
 public void useAxe() {  
 // 调用axe的chop方法,表明Person对象依赖于Axe对象  
     System.out.println("我是"+name+"用"+axe.chop());  
 }  
}  
Spring采用了XML文件作为配置文件。对于本应用的XML配置文件如下:
<!-- 配置Chinese实例,其实现类是Chinese -->  
<bean id="chinese" class="com.spring.service.impl.Chinese"> 
  <!-- 将StoneAxe注入给axe属性 -->  
  <property name="axe" ref="stoneAxe" />  
  <property name="name" value="孙悟空"/>  
</bean>  
<!-- 配置stoneAxe实例 -->  
<bean id="stoneAxe" class="com.spring.service.impl.StoneAxe" />  

Spring会自动接管每个<bean>定义里的<property>元素定义,Spring会在调用无参数的构造器、创建默认的Bean实例后,调用相应的setter方法为程序注入属性值。<property>定义的属性值将不再有该Bean来主动设置、管理,而是接受Spring的注入。

      !!!注意<property>识别的是setter方法,即setAxe和setName。不需要匹配字段axe、name。!!!


      程序没有为Person实例传入Axe实例,Axe实例由Spring在运行期间注入。Bean与Bean之间的依赖关系由Spring管理,Spring采用setter方法为目标Bean注入所依赖的Bean,这种方式被称之为设值注入。
      从上面的实例可以看出,依赖注入以配置文件管理Bean实例之间的耦合,让Bean实例之间的耦合从代码层次分离出来。
  
二、构造注入
构造注入就是利用构造函数来设置依赖关系的方式。
public class Japanese implements Person{  
 private Axe axe;  
 //默认构造器  
 public Japanese(){       
 }  
 //构造注入所需的带参数构造器  
 public Japanese(Axe axe){  
     this.axe = axe;  
 }  
 public void useAxe() {  
     System.out.println(axe.chop());  
 }  
}
为了使用构造注入,使用<constructor-arg>元素来指定构造器的参数。如下
<!-- 配置Japanese实例 -->  
<bean id="japanese" class="com.spring.service.impl.Japanese">
<!-- 使用构造注入 ,为Japanese实例注入SteelAxe实例-->  
<constructor-arg ref="stoneAxe"/>  
</bean>  
<!-- 配置stoneAxe实例 -->  
<bean id="stoneAxe" class="com.spring.service.impl.StoneAxe" />
上面的配置文件使用<contructor-arg>元素指定了一个构造器参数,该参数类型是Axe,这指定Spring调用Chinese类里带一个Axe参数的构造器来创建chinese实例,因为使用了有参数的构造器创建实例,所以当Bean实例被创建完成后,该Bean的依赖关系也就已经设置完成。
<constructor-arg index="1" value="007"></constructor-arg>
<constructor-arg index="0" value="23"></constructor-arg>
可用index来指明第几个参数。
当参数是其他类型时,用<set><list><map><props>。。。
 
      设值注入式先通过无参数的构造器创建一个Bean实例,然后调用它的setter方法注入依赖关系,而构造注入则是直接调用有参数的构造器,当Bean实例创建完成后,依赖关系也已经完成。
       Spring支持两种依赖注入方式,这两种依赖注入方式并没有好坏之分,只是适合的场景有所不同。
       设值注入有如下优点:
             1、与传统的JavaBean的写法更相似,程序开发人员更加容易理解,接受。通过setter方法设定依赖关系显得更加直观、自然。 
             2、对于复杂的依赖关系,如果采用构造注入,会导致构造器过于臃肿,难以阅读。Spring在创建Bean实例时,需要同时实例化其依赖的全部实例,因此导致性能下降。而设值注入,则可以避免这些问题。
             3、尤其是在某些属性可选的情况下,多参数的构造器更加笨重。
       但是构造器也有如下优势:
             1、构造注入可以再构造器中决定依赖关系的注入顺序,优先依赖的优先注入。
             2、对于依赖关系无须变化的Bean,构造注入更有用处。因为没有setter方法,所有的依赖关系全部在构造器中设定,因此,无须担心后续的代码对依赖关系产生破坏。
             3、依赖关系只能在构造器中设定,则只有组件的创建者才能改变组件的依赖关系。对组件的调用者而言,组件内部的依赖关系完全透明,更加符合高内聚的原则。
   
       通过上面的对比。所以建议用以设值注入为主,构造注入为辅的注入策略。对于依赖关系无须变化的注入,尽量采用构造注入;而其他的依赖关系,则考虑设值注入。

三.  注解注入
注解方式就不再需要setter方法。在beans.xml中是需要定义bean就可以了。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
					http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
					http://www.springframework.org/schema/context 
					http://www.springframework.org/schema/context/spring-context-2.5.xsd
					">

	<!-- 注解注入 -->
	<bean id="person" class="com.zero.dao.impl.PersonDaoBean"></bean>
	<bean id="personServiceBean" class="com.zero.service.impl.PersonServiceBean" ></bean>

</beans>
手动方式:
一.@Autowired默认按类型匹配注入
     1.@Autowired private PersonDaoBean client;
        //默认按类型匹配注入,会找到PersonDaoBean类型的bean,然后注入
     2.@Autowired @Qualifier("person")private PersonDaoBean client;
        //配合使用可以按名称匹配,会找到id为person的bean,然后注入
     3.@Autowired(required=false) @Qualifier("persons")private PersonDaoBean client;
        //false时,按名称未找到时client可以赋值为null,true时,按名称未找到时就抛出异常

二.@Resource默认按名称匹配注入,即可以指定name,当找不到名称时才按类型装配
     1.@Resource(name="person") private PersonDaoBean client;
         或则:
     2.@Resource
        public void setClient(PersonDaoBean client) {
       this.client = client;
        }
        //当直接使用@Resource private PersonDaoBean client;即未指定idname,则会根据变量名client去寻找跟client匹配的Bean,若未找到,则按类型来匹配注入。

在Spring2.5以后有组件自动扫描机制:让标注了一下注解的类自动成为被Spring管理的Bean。   
@Component  泛指组件
@Service 业务层
@Controller 控制层
@Repository 数据访问层DAO

@Service("personService")
public class PersonServiceBean implements IPersonService {}
默认获取Bean时例如对PersonServiceBean类,用getBean(“personServiceBean”)获得。
可以指定作用域 @Scope(“prototype”)
在init()函数前加@PostConstruct实现init-method功能

@PreDestory实现destory-method功能




XML配置 <context:annotation-config /> 是告诉spring 容器采用自动扫描注解配置,

当然也可以通过添加如下bean来开启扫描注解配置:
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />

你可能感兴趣的:(IOC)