Spring基础:IoC容器(1)

在IoC容器中装配Bean

4.1.2.RELEASE版本的Spring支持3种配置方式
  • 基于XML配置
  • 基于注解
  • 基于Java类


1.基于XML的配置
    这种方式是经典方式,即使Spring不断发展,也必须向前兼容这种方式。装配一个Bean有3种方式。
1.1 属性注入
    这种方式是最常用的方式,基于POJO类中的Set方法,为属性注入参数。
public class Car {
    private int maxSpeed;
    private String brand;
    private double price;
    // Getter Setter
    // introduce方法将各参数打印出来
}

<bean id="car" class="com.firethewhole.maventest05.ditype.Car">
    <property name="maxSpeed"><value>100</value></property>
    <property name="brand"><value>红旗CA97</value></property>
    <property name="price"><value>20000.00</value></property>
</bean>

可以在main方法中使用如下方法可以访问
ApplicationContext application = new ClassPathXmlApplicationContext("applicationContext.xml");
Car car = (Car) application.getBean("car");
System.out.println(car.introduce());

*****需要注意的是,在配置Bean的Property时,比如<property name="brand"/>,Spring仅要求必须存在setBrand()方法,不一定要拥有brand成员变量

1.2 构造函数注入
1.2.1 按构造函数的参数的类型进行匹配入参
public Car(String brand, double price) {
    this.brand = brand;
    this.price = price;
}

<bean id="car" class="com.firethewhole.maventest05.ditype.Car">
    <constructor-arg type="java.lang.String">
        <value>红旗CA72</value>
    </constructor-arg>
    <constructor-arg type="int">
        <value>70</value>
    </constructor-arg>
    <constructor-arg type="double">
        <value>20000</value>
    </constructor-arg>
</bean>

****注意,这种方式,根据入参类型就可以确定如何绑定的情况下不需要保证顺序和Java构造方法的参数顺序一致。

1.2.2 按索引匹配入参
如果入参存在两个相同类型的参数,那使用上面一种方式就没办法唯一确定了,这个时候需要根据入参的索引来确定,第一个参数的索引是"0",第二个是"1",一次类推
<bean id="car" class="com.firethewhole.maventest05.ditype.Car"><bean id="car" class="com.firethewhole.maventest05.ditype.Car">
    <constructor-arg index="0" value="红旗CA72" />
    <constructor-arg index="1" value="中国一汽" />
    <constructor-arg index="2" value="20000" />
</bean>


1.2.3 联合使用类型和索引匹配入参
如果分别使用上面两种方式还是没有办法绑定,比如有多个构造函数,其中有一个参数类型不同,这种情况下可以联合使用上面两种方法。

1.2.4 通过反射匹配入参
如果入参的类型是可以辨别的,比如自定义的Car类,Office类这种,在构造函数中引用了这些类,在XML配置的时候,可以不加type和index,由框架自动注入。
public Boss(String name, Car car, Office office) {
    // 省略
}

<bean id="boss" type="com.firethewhole.maventest05.ditype.Boss">
    <consturctor-arg>
        <value>John</value>
    </constructor-arg>
    <constructor-arg>
        <ref bean="car"/>
    </constructor-arg>
    <constructor-arg>
        <ref bean="office"/>
    </constructor-arg>
</bean>
<bean id="car" class="com.firethewhole.maventest05.ditype.Car"/>
<bean id="office" class="com.firethewhole.maventest05.ditype.Office"/>


1.3 工厂方法注入
分静态工厂方法和非静态工厂方法,这种方法在IoC中用的不多,就跳过不提了。

2.基于注解的方式
    基于XML的方式实在过繁杂,书写起来也容易犯错,所以现在更多的是使用基于注解的方式。
在使用基于注解的方式配置Bean之前,需要先告诉Spring有哪些程序包是需要被扫描的
<context-component-scan base-package="com.firethewhole.maventest05.anno/>
以上只是最简单的方式,还可以在其中配置和除外和包含的基于正则或其他方式的匹配。

然后在Bean定义时,对类加上@Component,@Repository,@Service,@Controller之类的注解即可。
对类中定义的属性可以使用@Autowired进行自动注入,会按照优先类型匹配的方式进行自动注入。

required属性,在没有匹配的时候也不会报错,这个值默认是true
@Qualifier注解可以指定注入的Bean的名称,
@Scope注解Bean的作用范围
@PostConstruct,@PreDestroy对应init-method和destroy-method

3.基于Java类的注解
这种方式由@Configuration注解定义配置文件Java类,通过@Bean进行Bean的定义。通常对程序员更加友好。
3.1 标准方式
@Configuration
public class AppConf {
    @Bean
    public UserDao userDao() {
    	return new UserDao();
    }
    
    @Bean
    public LogDao logDao() {
    	return new LogDao();
    }
    
    @Bean
    public LogonService logonService() {
    	LogonService logonService = new LogonService();
    	logonService.setUserDao(userDao());// 看下面注释
    	logonService.setLogDao(logDao());
    	return logonService;
    }
}


通过以下方式可以启动容器
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConf.class);
LogonService logonService = ctx.getBean(LogonService.class);
logonService.printHello();


像上面这个例子里面,UserDao和LogDao实际上是加上了Getter Setter方法的,实际上没必要在这两个Dao中加上Setter方法,只需要在LogonService中给这两个属性加上@Autowired注解,就会自动注入了。

3.2 多Config文件组合
@Configuration
public class DaoConfig {
    @Bean
    public UserDao userDao() {
    	return new UserDao();
    }
    
    @Scope("prototype")
    @Bean
    public LogDao logDao() {
    	return new LogDao();
    }
}

@Configuration
@Import(DaoConfig.class) // 使用这行代码就就可以引用其他的注解配置类
public class ServiceConfig {
    @Autowired
    private DaoConfig daoConfig;
    
    @Bean
    public LogonService logonService() {
    	LogonService logonService = new LogonService();
        // 这里没有加上Setter方法,是因为LogonService中使用了Autowired注解
    	return logonService;
    }
}


如下,如果没有使用Import注解的话,需要在启动容器的时候,把所有的Java注解配置类都注册上
AnnotationConfigApplicationContext ctx1 = new AnnotationConfigApplicationContext();
// ctx1.register(DaoConfig.class); // 如果没有使用Import注解的话,一定要记得加上
ctx1.register(ServiceConfig.class);
ctx1.refresh();
LogonService logonService1 = ctx1.getBean(LogonService.class);
logonService1.printHello();


3.3 在XML配置中引用@Configuration配置,很简单,只需要<context:component-scan>可以扫描到即可。

3.4 在Configuration中引用XML配置信息,只需要在类上加上@ImportResource("classpath:com/firethewhole/conf/bean3.xml"),然后对应的每个方法都需要参数并且加上Autowired属性
@Configuration
@ImportResource("classpath:beans3.xml")
public class LogonAppConfig {
    @Bean
    @Autowired
    public LogonService logonService(UserDao userDao, LogDao logDao) {
        LogonService logonService = new LogonService();
        logonService.setLogDao(logDao);
        logonService.setUserDao(userDao);
        return logonService;
    }
}

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">	
    <bean id="userDao" class="com.firethewhole.maventest05.dao.UserDao"/>
    <bean id="logDao" class="com.firethewhole.maventest05.dao.LogDao"/>
</beans>

猜你喜欢

转载自foreversky12.iteye.com/blog/2335949