Bean的自动装配

  • 自动装配是Spring满足bean依赖的一种方式!
  • Spring会在应用上下文中为某个bean寻找其依赖的bean。

在Spring中有三种装配的方式:

  1. 在xml中显示的配置
  2. 在java中显示配置
  3. 隐式的自动装配bean

一、测试

环境搭建:一个人有两个宠物!

二、ByName自动装配

1
2
3
4
5
6
<!--
byName:会自动在容器上下文中查找,和自己对象Set方法后面的值对应的beanid
-->
<bean id="people" class="com.nichu.pojo.People" autowire="byName">
<property name="name" value="倪"/>
</bean>

三、ByType自动装配

1
2
3
4
5
6
7
8
9
<bean id="cat" class="com.nichu.pojo.Cat"/>
<bean id="dog" class="com.nichu.pojo.Dog"/>
<!--
byName:会自动在容器上下文中查找,和自己对象Set方法后面的值对应的beanid
byType:会自动在容器上下文中查找,和自己对象属性类型相同的bean
-->
<bean id="people" class="com.nichu.pojo.People" autowire="byType">
<property name="name" value="倪"/>
</bean>

小结:

  • byName的时候,需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法一致!
  • byType的时候,需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性类型一致!

四、使用注解实现自动装配

要使用注解须知:

  1. 导入约束:context约束
  2. 配置注解的支持:context:annotation-config
1
2
3
4
5
6
7
8
9
10
11
12
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">

<context:annotation-config/>

</beans>

4.1 @Autowired

  • 直接在属性上使用即可!也可以在set方法上使用!

  • 使用Autowired我们可以不用编写Set方法了,前提是你这个自动装配的属性在IOC(Spring)容器中存在,且符合名字byName!

1
@Nullable 字段标记了这个注解,说明这个字段可以为null
1
2
3
public @interface Autowired {
boolean required() default true;
}

测试代码

1
2
3
4
5
6
7
8
public class People {
//如果显示定义了Autowired的require值为false,说明这个对象可以为null,否则不允许为空
@Autowired(required = false)
private Cat cat;
@Autowired
private Dog dog;
private String name;
}

如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解【@Autowired】完成的时候,我们可以使用@Qualifier(value = “xxx”)去配合@Autowired的使用,指定一个唯一的bean对象注入!

4.2 @Resource

1
2
3
4
5
6
7
public class People {
@Resource(name="cat2")
private Cat cat;
@Resource
private Dog dog;
private String name;
}
  • @Resource既有byName也有byType
  • 当byName找不到时,会自动使用byType
  • 当byType重复时,可以通过@Resource(name=“xxx”)去指定

小结:

@Resource和@Autowired的区别:

  1. 都是用来自动装配的,都可以放在属性字段上
  2. @Autowired默认通过byType的方式实现,如果找到相同类型,就通过byName实现!【常用】
  3. @Resource默认通过byName的方式实现,如果找不到名字,则通过byType实现!如果两个都找不到的情况下,就报错。【常用】
  4. 执行顺序不同:@Autowired默认通过byType的方式实现,@Resource默认通过byName的方式实现。

五、Spring使用注解开发

在Spring4之后要使用注解开发,需要保证aop的包导入了。要添加context约束,配置注解支持。

1
2
3
<!--指定要扫描的包,这个包下的注解就会生效-->
<context:component-scan base-package="com.nichu.entity"/>
<context:annotation-config/>

5.1 常用注解

  • @Autowired:自动装配通过类型,名字。

  • @Resource:自动装配通过名字,类型。

  • @Nullable:字段标记了这个注解,说明这个字段可以为空。

  • @Component:放在类上,说明这个类被Spring管理了。

    1
    2
    3
    4
    5
    6
    7
    /**
    * @Component等价于<bean id="user" class="com.nichu.entity.User"/>
    */
    @Component
    public class User {
    public String name = "倪矗";
    }
  • @Value:给属性注入值。

    1
    2
    3
    4
    5
    6
    @Component
    public class User {
    //相当于 <property name="name" value="倪矗"/>
    @Value("倪矗")
    public String name;
    }

    也可以写在set方法上

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @Component
    public class User {
    private String name;
    //相当于 <property name="name" value="倪矗"/>
    @Value("倪矗")
    public void setName(String name) {
    this.name = name;
    }
    public String getName() {
    return name;
    }
    }

5.2 衍生注解

@Component有几个衍生注解,我们在web开发中会按照三层架构分层!

  • dao:@Repository
  • service:@Service
  • controller:@Controller

这四个注解功能都是一样的,都是代表将某个类注册到Spring中。

5.3 作用域注解

@Scope:可以设置Bean的作用域。

1
2
3
4
5
6
7
8
9
@Scope("singleton")			//单例模式
public class User {
...
}

@Scope("prototype") //原型模式
public class User {
...
}

5.4 小结

xml和注解:

  • xml更加万能,适用于任何场合,维护简单!
  • 注解不是直接的类使用不了,维护相对复杂!

xml与注解配合使用:

  • xml用来管理bean。
  • 注解只负责属性的注入。

六、使用Java的方式配置Spring

实体类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Component
public class User {
private String name;
public String getName() {
return name;
}

@Value("倪矗")
public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}

配置类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//@Configuration代表这是一个配置类,相当于bean.xml
@Configuration
@ComponentScan("com.nichu.entity") //使用注解扫描包
@Import(UserConfig2.class) //导入其他的配置
public class UserConfig {

//注册一个bean,相当于xml里的一个bean标签
//方法名相当于bean标签的id属性
//返回值相当于bean的class属性
@Bean
public User getUser(){
return new User(); //就是返回要注入到bean的对象!
}
}

测试类:

1
2
3
4
5
6
7
8
public class MyTest {
public static void main(String[] args) {
//如果完全使用了配置类的方式去做,我们就只能通过AnnotationConfig上下文的方式获取容器,通过配置类的对象加载。
ApplicationContext context = new AnnotationConfigApplicationContext(UserConfig.class);
User user = context.getBean("getUser", User.class);
System.out.println(user.getName());
}
}
-------------本文结束感谢您的阅读-------------