XML方式装配Bean
装配Bean的方式分为通过XML装配和通过注解装配两种方式。通过xml装配是指在XML文件中添加bean元素,这里不详细讨论,只给出一个简单的例子:
<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.0.xsd">
<bean id="source" class="com.ssm.chapter9.pojo.Source">
<property name="fruit" value="橙汁" />
<property name="sugar" value="少糖" />
<property name="size" value="大杯" />
</bean>
<bean id="juiceMaker2" class="com.ssm.chapter9.pojo.JuiceMaker2">
<property name="beverageShop" value="贡茶" />
<property name="source" ref="source" />
</bean>
</beans>
和一个属性为集合的例子:
<bean id="role1" class="com.ssm.chapter10.pojo.Role">
<property name="id" value="1" />
<property name="roleName" value="role_name_1" />
<property name="note" value="role_note_1" />
</bean>
<bean id="role2" class="com.ssm.chapter10.pojo.Role">
<property name="id" value="2" />
<property name="roleName" value="role_name_2" />
<property name="note" value="role_note_2" />
</bean>
<bean id="user1" class="com.ssm.chapter10.pojo.User">
<property name="id" value="1" />
<property name="userName" value="user_name_1" />
<property name="note" value="role_note_1" />
</bean>
<bean id="user2" class="com.ssm.chapter10.pojo.User">
<property name="id" value="2" />
<property name="userName" value="user_name_2" />
<property name="note" value="role_note_1" />
</bean>
<bean id="userRoleAssembly" class="com.ssm.chapter10.pojo.UserRoleAssembly">
<property name="id" value="1" />
<property name="list">
<list>
<ref bean="role1" />
<ref bean="role2" />
</list>
</property>
<property name="map">
<map>
<entry key-ref="role1" value-ref="user1" />
<entry key-ref="role2" value-ref="user2" />
</map>
</property>
<property name="set">
<set>
<ref bean="role1" />
<ref bean="role2" />
</set>
</property>
</bean>
- 还有一种是XML中使用命名空间装配Bean,不再详细介绍。
注解方式转配Bean
- 下面讨论通过注解的方式装配Bean,首先介绍第一个注解@Component,该注解放在需要被Spirng IoC管理的Bean的类上方。
- 第二个注解是@ComponentScan,该注解放在配置类(Java Config)的上面,用来告诉Spring哪些包里面的类是需要被扫描的。这些包里面所有被@Component注解修饰的类都会被装配。
- 给一个简单的例子,分别看看两个注解所在的位置。
package com.ssm.chapter10.annotation.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component(value = "role")//value相当于xml中的id
public class Role {
@Value("1")//属性注入,注入简单的值
private Long id;
@Value("role_name_1")
private String roleName;
@Value("role_note_1")
private String note;
/** getter and setter **/
Java Config类
package com.ssm.chapter10.annotation.pojo;
import org.springframework.context.annotation.ComponentScan;
//注解@ComponentScan的属性basePackageClasses或者basePackages用来指明需要扫描的包以及子包。
@ComponentScan(basePackageClasses = { Role.class, RoleServiceImpl.class })
// @ComponentScan(basePackages = {"com.ssm.chapter10.annotation.pojo",
// "com.ssm.chapter10.annotation.service"})
public class PojoConfig {
}
有了这两部分,就能够通过Spring定义好的Spring IoC容器的实现类——AnnotationConfigApplicationContext去生成IoC容器了:
ApplicationContext context = new AnnotationConfigApplicationContext(PojoConfig.class);
Role role = context.getBean(Role.class);//再通过ApplicationContext中的getBean方法得到bean对象
System.err.println(role.getId());
前面的Role类的属性是比较简单的,如果遇到了稍微复杂点的属性,我们通常是用自动装配的方式,而不是在属性上面加@Value注解。
注解方式装配Bean之使用@Bean注解
@Component注解是放在类之上,而@Bean注解则放到方法之上,并将方法返回的对象作为Spring的Bean,存放在IoC容器中。例如DBCP数据源:
@Bean(name = "dataSource")//当Spring IoC容器扫描它的时候,就会为其生成对应的Bean
public DataSource getDataSource() {
Properties props = new Properties();
props.setProperty("driver", "com.mysql.jdbc.Driver");
props.setProperty("url", "jdbc:mysql://localhost:3306/chapter10");
props.setProperty("username", "root");
props.setProperty("password", "123456");
DataSource dataSource = null;
try {
dataSource = BasicDataSourceFactory.createDataSource(props);
} catch (Exception e) {
e.printStackTrace();
}
return dataSource;
}
自动装配——@Autowired
自动装配技术是由Spring自己发现对应的Bean,自动完成装配工作(属性注入)。例如下面的RoleService2类中的role属性。
package com.ssm.chapter10.annotation.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ssm.chapter10.annotation.pojo.Role;
import com.ssm.chapter10.annotation.service.RoleService2;
@Component("RoleService2")
public class RoleServiceImpl2 implements RoleService2 {
@Autowired//加在需要自动寻找对象并注入的属性上方,也可以是它的setter方法上。
private Role role = null;
public Role getRole() {
return role;
}
// @Autowired
public void setRole(Role role) {
this.role = role;
}
@Override
public void printRoleInfo() {
System.out.println("id =" + role.getId());
System.out.println("roleName =" + role.getRoleName());
System.out.println("note =" + role.getNote());
}
}
@Autowired注解是按照类型进行寻找并注入的,当属性为接口,而接口又不止一个实现类时就会报错,为了消除歧义,还有另外一个注解@Qualifier(“beanName”),放在属性的上面:
package com.ssm.chapter10.annotation.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import com.ssm.chapter10.annotation.pojo.Role;
import com.ssm.chapter10.annotation.service.RoleService;
@Component
public class RoleController {
@Autowired
@Qualifier("roleService3")
private RoleService roleService = null;
public void printRole(Role role) {
roleService.printRoleInfo(role);
}
}
此时,属性注入就会按照名字查找的方式,而非类型匹配的方式。实际上,这两种方式分别对应底层接口的两个方法。那就是BeanFactory的getBean方法:
<T> T getBean(Class<T> requiredType) throws BeansException;
Object getBean(String name) throws BeansException;
装配的混合使用
一般情况下我们都会两种同时使用,这时候需要将XML配置文件引入到注解的体系当中,引入时使用注解,放置的位置时是配置类(Java Config)的上面,跟@ComponentScan注解在一起。例如:
package com.ssm.chapter10.annotation.pojo;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ImportResource;
//注解@ComponentScan的属性basePackageClasses或者basePackages用来指明需要扫描的包以及子包。
//@ComponentScan(basePackageClasses = { Role.class, RoleServiceImpl.class })
@ComponentScan(basePackages = {"com.ssm.chapter10.annotation"})
@ImportResource({"classpath:spring-dataSource.xml"})
public class ApplicationConfig {
}
加入@ImportResource这个注解后,就能够在需要注入数据库连接池属性时通过@Autowired注解自动注入。spring-dataSource.xml的内容如下:
<?xml version='1.0' encoding='UTF-8' ?>
<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.0.xsd">
<bean id="dataSource1" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/chapter10" />
<property name="username" value="root" />
<property name="password" value="123456" />
</bean>
</beans>
多XML文件或多配置类引用
有时候我们会分开定义多个xml配置文件或者多个配置类,这时就需要在其中一个中引入其他。配置类的引用方式如下:
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
//注解@ComponentScan的属性basePackageClasses或者basePackages用来指明需要扫描的包以及子包。
//@ComponentScan(basePackageClasses = { Role.class, RoleServiceImpl.class })
@ComponentScan(basePackages = {"com.ssm.chapter10.annotation"})
@Import({ApplicationConfig2.class,ApplicationConfig3.class})//引入配置类
public class ApplicationConfig {
}
xml的引入方式如下:
<import resource="spring-datasource.xml"/>