spring基础知识 (15):使用注解自动装配bean

一般情况下,控制层(controller)需要调用业务层(service)进行业务逻辑处理,业务层调用持久层(dao)访问数据库。这时候就需要使用自动装配注入相应的bean.在controller中注入service,在service中注入repository。

使用 @Autowired 自动装配 Bean

通过属性注入

  • 创建持久层接口
package com.spring.annotation.repository;

public interface UserRepository {

    public void save();
}
  • 创建持久层实现类:
package com.spring.annotation.repository;

import org.springframework.stereotype.Repository;

@Repository("userRepository")
public class UserRepositoryImpl implements UserRepository{

    @Override
    public void save() {
        System.out.println("UserRepository save...");
    }

}
  • 创建业务层
package com.spring.annotation.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.spring.annotation.repository.UserRepository;

@Service
public class UserService {

    @Autowired(required=false)
    private UserRepository userRepository;

    public void save() {
        System.out.println("UserService save...");
        userRepository.save();
    }
}

使用注解注入了userRepository,并且调用userRepository的save方法

  • 创建控制层:
package com.spring.annotation.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import com.spring.annotation.service.UserService;

@Controller
public class UserController {

    @Autowired
    private UserService userService;

    public void save() {
        System.out.println("UserController save...");
        userService.save();
    }
}

使用注解注入了userService,并且调用userService的save方法

测试:

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-annotation.xml");

UserController uc = (UserController) ctx.getBean("userController");
uc.save();

spring基础知识 (15):使用注解自动装配bean_第1张图片

如果被注入的bean没有在bean容器中注册,使用@Autowired注解就会报错。可以在@Autowired中设置required=false标识可以为null.


通过setter方法注入

将@Autowired标识在setter方法上

package com.spring.annotation.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import com.spring.annotation.service.UserService;

@Controller
public class UserController {

    private UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void save() {
        System.out.println("UserController save...");
        userService.save();
    }
}

这种写法和上面效果一样


关于@Autowired

  • @Autowired是byType类型的
  • 在使用@Autowired时,首先在容器中查询对应类型的bean 如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据
    如果查询的结果不止一个,那么@Autowired会根据名称来查找。
  • 如果查询的结果为空,那么会抛出异常。解决方法时,使用required=false,可以为null

当@Autowired匹配到多个相同类的bean时会自动转换成byName方式
下面就这种情况进行详细讲解:
下面是转化为byName方式后的运行情况
- @Autowired标识在属性上,根据属性名去bean容器匹配bean的id。匹配到就将之注入。
如:
UserRepositoryImpl 类

@Repository("user1Repository")
public class UserRepositoryImpl implements UserRepository{

    @Override
    public void save() {
        System.out.println("UserRepository save...");
    }

}

User2RepositoryImpl 类

package com.spring.annotation.repository;

import org.springframework.stereotype.Repository;

@Repository(user2Repository)
public class User2RepositoryImpl implements UserRepository{

    @Override
    public void save() {
        System.out.println("User2Repository save...");
    }

}

定义了两个相同接口的类,一个注册为id = “user1Repository”的bean一个注册为id = “user2Repository”的bean.
注入:

@Autowired
private UserRepository user1Repository;
  • 这里先按类型匹配,但是出现两个相同类型的,这时候就转换成按名称匹配。

  • 这里属性名称为user1Repository,以byName方式匹配id = “use1Repository”的bean.

  • 如果标识在setter方法上,会先通过类型匹配,如果匹配了多个,则会使用方法参数名去匹配bean的id.

如:

private UserRepository userRepository;

@Autowired
public void setUserRepository(UserRepository user1Repository) {
    this.userRepository = user1Repository;
}

这里的setter方法的参数名为user1Repository 可以匹配到bean.

  • 也可以使用 @Qualifier注解声明按byName方式匹配并指定匹配的id.
@Autowired
@Qualifier("user1Repository")
private UserRepository userRepository;

这样就可以解放属性名,不用再使用属性名去匹配了。
使用@Qualifier注解后直接转换成byName方式

  • 也可用于setter方法上:
private UserRepository userRepository;

@Autowired
@Qualifier("user1Repository")
public void setUserRepository(UserRepository userRepository1) {
    this.userRepository = userRepository1;
}

或者

@Autowired
public void setUserRepository(@Qualifier("user1Repository") UserRepository userRepository1) {
    this.userRepository = userRepository1;
}
  • @Authwired 注解也可以应用在数组类型的属性上, 此时 Spring 将会把所有匹配的 Bean 进行自动装配.
  • @Authwired 注解也可以应用在集合属性上, 此时 Spring 读取该集合的类型信息, 然后自动装配所有与之兼容的 Bean.
  • @Authwired 注解用在 java.util.Map 上时, 若该 Map 的键值为 String, 那么 Spring将自动装配与之 Map 值类型兼容的 Bean, 此时 Bean 的名称作为键值

使用 @Resource 或 @Inject 自动装配 Bean

  • Spring 还支持 @Resource 和 @Inject 注解,这两个注解和 @Autowired 注解的功用类似
  • @Resource 注解是byName的,要求提供一个 Bean 名称的属性,若该属性为空,则自动采用标注处的变量名或setter方法入参名作为 Bean 的名称
  • @Inject 和 @Autowired 注解一样也是按类型匹配注入的 Bean, 但没有 reqired 属性
  • 建议使用 @Autowired 注解

本系列参考视频教程: http://edu.51cto.com/course/1956.html

你可能感兴趣的:(spring)