1.1.基于xml配置Bean
基于xml配置bean时,spring通过配置来实例化、设置bean的属性以及设置bean之间的相互依赖。
一个通常需要定义id和class属性。class属性是必须的,不然spring框架不知道是那个,id不是必要的,如果配置文件中配置的其他bean引用这个bean的话,那么id也是必要的,通常情况下都是加上的。
<bean id="DirthAir" class="com.gaolei.ioc.DirtyAir">
<qualifier value="dirthair"></qualifier>
</bean>
1.2使用注解定义Bean
如果采用xml配置,bean定义信息和bean实现类本身是分离的,而采用基于注解的配置方法时,bean定义信息就通过在bean实现类上标注注解实现。
@Component
public class DirtyAir implements IAir {
@Override
public String toString() {
return "DirtyAir";
}
}
使用@Component注解在DirtyAir类声明处进行标注,这样就可以自动的被spring容器所识别了,自动将POJO转化为spring容器管理的一个bean。和是一样的效果。
spring提供了以下几个和@Component等效的注解,
- @Repository:用于DAO实现类进行标注。
- @Service: 用于对Service实现类进行标注
- @Controller:用于对Controller实现类进行标注
1.3基于java类提供Bean定义
在普通的pojo类中只要标注@Configuration注解,就可以为spring容器提供bean定义信息,每个标注@Bean的类方法都相当于提供了一个bean的定义信息(省去了xml配置多个bean的烦恼了)
@Configuration
public class AppConf {
@Bean
public CleanAir cleanAir(){
return new CleanAir();
}
@Bean
public DirtyAir dirtyAir(){
return new DirtyAir();
}
@Bean
public Person person(){
return new Person(dirtyAir());
}
}
我们只需要在xml中配置开启context扫描就 可以实现bean的配置。
<bean id="conf" class="com.gaolei.entity.AppConf"></bean>
==============================================================
部分代码(有的注解和xml是重复了,本次只是写作案例,重复了我自己也就懒的改了):
@Component
public interface IAir {
}
@Component
public class CleanAir implements IAir{
@Override
public String toString() {
return "CleanAir";
}
}
@Component
public class DirtyAir implements IAir {
@Override
public String toString() {
return "DirtyAir";
}
}
public class Person {
@Autowired
public Person(@Qualifier("dirthair") IAir iAir) {
this.iAir = iAir;
}
IAir iAir;
public void Breath(){
System.out.println(this.iAir.toString());
}
}
@Configuration
public class AppConf {
@Bean
public CleanAir cleanAir(){
return new CleanAir();
}
@Bean
public DirtyAir dirtyAir(){
return new DirtyAir();
}
@Bean
public Person person(){
return new Person(dirtyAir());
}
}
<?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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<context:component-scan base-package="com.gaolei.ioc"/>
<!-- <bean id="CleanAir" class="com.gaolei.ioc.CleanAir">
<qualifier value="cleanair"></qualifier>
</bean>
<bean id="DirthAir" class="com.gaolei.ioc.DirtyAir">
<qualifier value="dirthair"></qualifier>
</bean>
<bean id="Person" class="com.gaolei.ioc.Person">
</bean>-->
<bean id="conf" class="com.gaolei.entity.AppConf"></bean>
</beans>
Bean的注入
2.1XML方式注入
2.1.1属性注入:
在我们之前实例化一个对象的时候,我们都是通过new xxx来实现的,然后通过set()方法设置对象的属性值,现在spring框架也是这样操作的,只不过是在框架内部完成。spring容器会先调用bean的默认构造器实例化bean对象(默认的都是无参构造器),然后通过反射的方式调用setter()方法注入属性值。
public class XMLInstance {
private String name;
private IAir iAir;
public void setName(String name) {
this.name = name;
}
public void setiAir(IAir iAir) {
this.iAir = iAir;
}
public void Breath(){
System.out.println("Name:"+ this.name+"iAir:"+this.iAir.toString());
}
}
<!--属性注入 property配置属性 name:属性名字-->
<bean id="xmlinstance" class="com.gaolei.ioc.XMLInstance">
<property name="iAir" ref="cleanAir"></property>
<property name="name" value="hufan"></property>
</bean>
2.1.2构造函数注入:
在属性注入时会先使用默认的构造函数实例化,然后通过set方法注入属性,在传统实例化对象时可以自定义构造函数进行实例化,构造函数注入就是通过自定义构造函数来进行对象的实例化,现在对上面XMLInstance类做一点点改变。
public class XMLInstance {
private String name;
private IAir iAir;
public XMLInstance(String name, IAir iAir) {
this.name = name;
this.iAir = iAir;
}
public void Breath(){
System.out.println("Name:"+ this.name+"iAir:"+this.iAir.toString());
}
}
<bean id="xmlcontru" class="com.gaolei.ioc.XMLInstance">
<constructor-arg index="1" ref="cleanAir"></constructor-arg>
<constructor-arg index="0" value="hufan"></constructor-arg>
</bean>
2.2注解方式注入
2.2.1常用注解介绍
- @Autowired:默认按类型匹配注入bean,可以对类成员变量,方法以及构造函数进行标注,完成自动装配工作。在使用该注解的时候,首先会在容器中查询对应类型的bean,如果查询的结果为一个,就将bean装配给@Autowired指定的数据,如果不止一个的话,那么@Autowired会根据名称查找,如果查询结果为空,那么会抛出异常,解决方法时,使用requied=false
- @Qualifier:@Autowired默认是单例的,但是面向接口编程中,如果把一个属性设置为接口类型,一个接口有多个实现类,那么到底注入哪一个了,为了解决这个问题就用到了该注解,比如上面写的代码中就用到了这个注解@Autowired
public Person(@Qualifier(“dirthair”) IAir iAir) {
this.iAir = iAir;
}
3.@Resource:默认按名称匹配注入bean。要求提供一个bean名称的属性(就是这个属性是一个bean的名字),如果属性为空,就自动采用标注处变量名或者方法作为bean的名称,如果我们没有在使用@Resource时指定bean的名称,同时spring容器中又没有该名字的bean,这是@Resource就自动退化为@Autowired,按照类型注入。
4.@Value:在xml配置属性时候可以通过property的value设置默认值,@Value也可以为属性设置默认值。
public class AnnoIntance {
@Value("gaolei")
private String name;
private IAir air;
public void setName(String name) {
this.name = name;
}
@Resource(name = "CleanAir")
public void setAir(IAir air) {
this.air = air;
}
public void Breath(){
System.out.println("Name:"+ this.name+"iAir:"+this.air.toString());
}
}
开启注解后才生效:
<context:annotation-config/>