# 通过注解装配Bean
## 使用@Component 装配Bean
- 定义一个`POJO`:
```
@Component(value = "role")
public class Role {
@Value("1")
private Long id;
@Value("role_name_1")
private String roleName;
@Value("role_note_1")
private String note;
/*** setter and getter ***/
}
```
- **注解`@Component`代表Spring IoC会把这个类扫描生成`Bean`实例**
> - `value`
属性代表这个类在Spring中的`id` ,这就相当于XML方式定义的`Bean`的`id`
>> - 可以简写成`@Component("role")`
>> - 直接写成`@Component`,默认类名首字母小写为`id`
- 现在有了这个类,但是还不能进行测试,因为Spring IoC 并不知道需要去哪里扫描对象,这个时候可以使用一个`Java Config `来去告诉它
```
package com.ssm.chapter10.annotation.pojo;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan
public class PojoConfig {
}
```
- **包名和POJO一致**
- **`@ComponentScan`代表进行扫描,默认是扫描当前包的路径, `POJO`的包名和它保持一致才能扫描**
---
- 然后就可以通过`Spring`定义好的Spring IoC容器的
实现类`AnnotationConfigApplicationContext`去生成IoC容器(一般放在专门的`config`文件夹中)
```
public class AnnotationMain {
public static void main(String[] args){
ApplicationContext context = new AnnotationConfigApplicationContext(PojoConfig.class);
Role role = context.getBean(Role.class);
System.err.println(role.getId();
```
---
- 扫描多个包
```
//1
@ComponentScan(basePackages = {"com.ssm.chapter10.annotation.pojo",
"com.ssm.chapter10.annotation.service"})
//2
@ComponentScan(basePackages = {"com.ssm.chapter10.annotation.pojo",
"com.ssm.chapter10.annotation.service"},
basePackageClasses = {Role.class, RoleServiceImpl.class})
```
- 难以注入对象
- 配置复杂
## 自动装配 @Autowired(推荐)
```
@Component
public class RoleController {
@Autowired
private RoleService roleService = null;
//同时也可以通过方法配置自动装配
@Autowired
public void setRole(Role role){
this.role = role;
}
}
```
- IoC 容器有时候会寻找失败,在默认的情况下寻找失败它就会抛出异常,可以通过`@Autowired(required =false)`配置
- `@Autowired`是按**类型**,在存在多个相同类型的类时装配会失败
### 解决@Autowired歧义性
为了消除歧义性, `Spring` 提供了两个注解`@Primary` 和`@Qualifier`
- 注解`@Primary`代表首要的,配置在需要注入的类上,它是告诉Spring IoC 容器,请优先使用该类注入
- 注解`Qualifier`是通过按名称注入,常和`@component`等配合,例如
```
@Component("roleService3")
public class RoleServiceImpl3 implements RoleService {}
```
```
@Component
public class RoleController {
@Autowired
@Qualifier("roleService3")
private RoleService roleService = null;
}
```
## 使用@Bean 装配Bean
以上都是通过`@Component`装配`Bean` ,但是`@Component` 只能注解在类上,不能注解到方法上,这个时候我们可以使用`@Bean`来解决
- 比如我们需要使用DBCP 数据源, 这个时候要引入关于它的包
```
@Bean(name = "dataSource")
public DataSource getDataSource(
Properties props = new Properties();
props.setProperty("driver", ....);
props.setProperty("url", ....);
props.setProperty("username", ....);
props.setProperty("password", ....);
DataSource dataSource = null;
try {
dataSource = BasicDataSourceFactory.createDataSource(props);
} catch (Exception e) {
e.printStackTrace();
}
return dataSource;
}
```
**`@Bean`包含四个配置项**
> - `name`:是一个字符串数组,允许配置多个BeanName
> - `autowire`:标志是否是一个引用的Bean对象,默认值是`Autowire.NO`
> - `initMethod`:自定义初始化方法
> - `destroyMethod`:自定义销毁方法
```
@Bean(name="juiceMaker2", initMethod="init", destroyMethod="myDestroy")
public JuiceMaker2 initJuiceMaker2() {
JuiceMaker2 juiceMaker2 = new JuiceMaker2();
juiceMaker2.setBeverageShop("贡茶");
Source source = new Source();
source.setFruit("橙子");
source.setSize("大杯");
source.setSugar("少糖");
juiceMaker2.setSource(source);
return juiceMaker2;
}
```
# XML与注解混用
在现实中,使用XML或者注解各有道理,建议在自己的工程中所开发的类尽量使用注解方式,因为使用它并不困难, 甚至可以说
更为简单,而对于引入第三方包或者服务的类,尽量使用XML 方式,这样的好处是可以尽量对三方包或者服务的细节减少理解,也更加清晰和明朗。
- 例如:
配置数据源`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>
```
- 在`xxxxx-config.java`中导入数据源
```
@ImportResource({"classpath:spring-dataSource.xml"})
public class ApplicationConfig {
.....
}
```
- 最后就可以注入
```
@Autowired
DataSource dataSource = null;
```
**在有多个config文件或者多个xml文件时可以进行导入:**
```
@Import({ApplicationConfig2.class,ApplicationConfig3.class})
public class ApplicationConfig {
.....
}
```
以及
```
<import resource = "spring-config.xml"/>
```