Spring管理Bean(注解)-IOC

注解方式配置bean

  1. 基本介绍

    基于注解配置bean,主要是项目中开发的组件,比如 Controller、Service、DAO

  2. 组件注解的形式

    • @Component 表示当前注解标识的是一个组件(不确定是哪一层时用Component)
    • @Controller 表示当前注解标识的是一个控制器, 通常用于 Servlet
    • @Service 表示当前注解标识的是一个处理业务逻辑的类, 通常用于 Service 类
    • @Repository 表示当前注解标识的是一个持久化层的类, 通常用于 Dao 类
  3. 配置bean.xml文件

    常规配置被扫描包路径

    1
    <context:component-scan base-package="fullPath" />

    【注意】

    1. 使用注解配置bean时,需要引入aop的jar
    2. 需要导入context名称空间
    3. base-package=”fullPath” 是指定需要扫描的包,ioc容器将检测该包及其子包中被注解标识了的类
    4. 路径也可以用通配符来表述,com.mhl.spring.* ,即spring下面的所有包及其子包

    指定需要扫描的资源模式

    1
    2
    <!--->将会扫描dao包下,由User开头的类<--->
    <context:component-scan base-package="com.mhl.spring.dao" resource-pattern="User*.class"/>

    排除指定的注解类

    1
    2
    3
    4
    <!--->排除由Repository注解标识的类<--->
    <context:component-scan base-package="com.example">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
    </context>

    扫描指定的注解类

    1
    2
    3
    4
    <!--->扫描由Repository注解标识的类<--->
    <context:component-scan base-package="com.example" use-default-filters="false">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
    </context>

    【注意】和排除不同的是,需要将默认的过滤机制设为false。

  4. id

    默认情况下,标记注解后,类名首字母小写作为id的值,也可以使用注解的value属性指定id值,并且value可以省略。

    1
    2
    @Controller(value="userAction01")
    @Controller("userAction01")

自动装配

@AutoWired 和 @Resource

  1. @AutoWired

    规则说明:

    1. 在 IOC 容器中查找待装配的组件的类型,如果有唯一的 bean 匹配,则使用该 bean 装配
    2. 如待装配的类型对应的 bean 在 IOC 容器中有多个,则使用待装配的属性的属性名作为 id 值再进行查找, 找到就装配,找不到就抛异常
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @Service
    public class UserService {
    public void hi(){
    System.out.println("UserService hi()~");
    }
    }

    @Controller("userAction01")
    public class UserAction {
    @Autowired
    private UserService userService;
    public void sayOk(){
    System.out.println("UserAction.userService= " + userService);
    userService.hi();
    }

    【注意】

    1. 如果没有加@AutoWired注解,是不能装配到userService的
    2. 加上@AutoWired注解后,如果ioc容器中只有一个UserService的bean,那么直接将该bean装配
    3. 如果ioc容器有多个UserService的bean,那么就根据userService去查找,如果找到则装配,找不到抛出异常

    @AutoWired可以搭配@Qualifier使用

    1
    2
    3
    4
    @Autowired
    @Qualifier(value = "userService02")
    //指定 id=userService02 的 UserService 对象进行组装
    //等价于@Resource(name = "userService")
  2. @Resource

    规则说明:

    1. @Resource 有两个属性是比较重要的,分是 name 和 type,Spring 将@Resource 注解的name 属性解析为 bean 的名字,而 type 属性则解析为 bean 的类型.所以如果使用 name 属性,则使用 byName 的自动注入策略,而使用 type 属性时则使用 byType 自动注入策略
    2. 如果@Resource 没有指定 name 和 type ,则先使用byName注入策略, 如果匹配不上,再使用 byType 策略, 如果都不成功,就会报错
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    @Service
    public class UserService {
    public void hi(){
    System.out.println("UserService hi()~");
    }
    }

    @Controller("userAction")
    public class UserAction {

    //通过name注入,name即为ioc容器中配置的id,注解方式配置的即为类名首字母小写
    @Resource(name = "userService")
    //通过type注入
    //@Resource(type = UserService.class)
    private UserService userService;

    public void hello(){
    System.out.println("say hello...");
    userService.hi();
    }
    }

    【说明】:不管是@AutoWired还是@Resource都保证属性名规范写法(即类名首字母小写)就可以注入

  3. 泛型依赖注入

    在继承关系复杂情况下,传统方法是将 PhoneDao /BookDao 自动装配到BookService/PhoneSerive 中,当这种继承关系多时,就比较麻烦,而泛型依赖注入可以简化bean的装配

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    public class Book {} 

    public class Phone {}

    public abstract class BaseDao<T> {
    public abstract void save();
    }

    @Repository
    public class BookDao extends BaseDao<Book> {
    @Override
    public void save() {
    System.out.println("BookDao 的 save()");
    }
    }

    @Repository
    public class PhoneDao extends BaseDao<Phone> {
    @Override
    public void save() {
    System.out.println("PhoneDao 的 save()");
    }
    }

    public class BaseService<T> {
    @Autowired
    private BaseDao<T> baseDao;
    public void save() {
    baseDao.save();
    }
    }

    @Service
    public class BookService extends BaseService<Book> {}

    @Service
    public class PhoneService extends BaseService<Phone> {}

    通过以上所示的泛型依赖注入,就可以在BookService中装配到BookDao对象