目录
一、IoC介绍
二、Bean存储
2.1 @Controller(控制器存储)
2.1.1 获取bean对象的其他方式
2.1.2 Bean的命名约定
2.2 @Service(服务存储)
2.3 @Repository(仓库存储)
2.4 @Component(组件存储)
2.5 @Configuration(配置存储)
2.6 方法注解@Bean
2.6.1 方法注解的使用
2.6.2 定义多个对象
2.6.3 重命名Bean
2.7 扫描路径
Spring存储对象的注解有:
@Controller // 将对象存储到 Spring 中
public class UserController {
public void sayHi(){
System.out.println("hi,UserController...");
}
}
从Spring容器中获取对象:
@SpringBootApplication
public class SpringIocDemoApplication {
public static void main(String[] args) {
//获取Spring上下⽂对象
ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);
//从Spring上下⽂中获取对象
UserController bean = context.getBean(UserController.class);
//使⽤对象
bean.sayHi();
}
ApplicationContext,也就是Spring上下文,Spring的运行环境。
运行结果如下:
public interface BeanFactory {
//以上省略...
// 1. 根据bean名称获取bean
Object getBean(String var1) throws BeansException;
// 2. 根据bean名称和类型获取bean
T getBean(String var1, Class var2) throws BeansException;
// 3. 按bean名称和构造函数参数动态创建bean,只适⽤于具有原型(prototype)作⽤域的bean
Object getBean(String var1, Object... var2) throws BeansException;
// 4. 根据类型获取bean
T getBean(Class var1) throws BeansException;
// 5. 按bean类型和构造函数参数动态创建bean, 只适⽤于具有原型(prototype)作⽤域的bean
T getBean(Class var1, Object... var2) throws BeansException;
//以下省略...
}
类名: UserController, Bean的名称为: userController类名: AccountManager, Bean的名称为: accountManager类名: AccountService, Bean的名称为: accountService
类名: UController, Bean的名称为: UController类名: AManager, Bean的名称为: AManager
根据这个命名规则,以下方法可以获取Bean:
@SpringBootApplication
public class SpringIocDemoApplication {
public static void main(String[] args) {
//获取Spring上下⽂对象
ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);
//从Spring上下⽂中获取对象
//根据bean类型, 从Spring上下⽂中获取对象
UserController userController1 = context.getBean(UserController.class);
//根据bean名称, 从Spring上下⽂中获取对象
UserController userController2 = (UserController)context.getBean("userController");
//根据bean类型+名称, 从Spring上下⽂中获取对象
UserController userController3 = context.getBean("userController",UserController.class);
System.out.println(userController1);
System.out.println(userController2);
System.out.println(userController3);
}
}
获取bean对象, 是父类BeanFactory提供的功能。常见面试题:
ApplicationContext VS BeanFactory
- 继承关系和功能方面来说:Spring 容器有两个顶级的接口:BeanFactory 和 ApplicationContext。其中 BeanFactory 提供了基础的访问容器的能力,而 ApplicationContext 属于 BeanFactory 的子类,它除了继承了 BeanFactory 的所有功能之外, 它还拥有独特的特性,还添加了对国际化支持、资源访问支持、以及事件传播等方面的支持。
- 从性能方面来说:ApplicationContext 是一次性加载并初始化所有的 Bean 对象,而BeanFactory 是需要哪个才去加载哪个,因此更加轻量。(空间换时间)
使用@Service 存储 bean 的代码如下所示:
@Service
public class UserService {
public void sayHi(String name) {
System.out.println("hi,UserService...");
}
}
@SpringBootApplication
public class SpringIocDemoApplication {
public static void main(String[] args) {
//获取Spring上下⽂对象
ApplicationContext context =
SpringApplication.run(SpringIocDemoApplication.class, args);
//从Spring中获取UserService对象
UserService userService = context.getBean(UserService.class);
//使⽤对象
userService.sayHi();
}
}
运行结果如下:
使用@Repository存储bean的代码如下:
@Repository
public class UserRepository {
public void sayHi() {
System.out.println("Hi,UserRepository...");
}
}
读取bean的代码:
@SpringBootApplication
public class SpringIocDemoApplication {
public static void main(String[] args) {
//获取Spring上下⽂对象
ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);
//从Spring上下⽂中获取对象
UserRepository userRepository = context.getBean(UserRepository.class);
//使⽤对象
userRepository.sayHi();
}
}
运行结果如下:
使用@Component存储bean的代码如下:
@Component
public class UserComponent {
public void sayHi() {
System.out.println("Hi,UserComponent...");
}
}
读取bean的代码:
@SpringBootApplication
public class SpringIocDemoApplication {
public static void main(String[] args) {
//获取Spring上下⽂对象
ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);
//从Spring上下⽂中获取对象
UserComponent userComponent = context.getBean(UserComponent.class);
//使⽤对象
userComponent.sayHi();
}
}
运行结果如下:
@Configuration
public class UserConfiguration {
public void sayHi() {
System.out.println("Hi,UserConfig...");
}
}
读取bean的代码:
@SpringBootApplication
public class SpringIocDemoApplication {
public static void main(String[] args) {
//获取Spring上下⽂对象
ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);
//从Spring上下⽂中获取对象
UserConfiguration userConfiguration = context.getBean(UserConfiguration.class);
//使⽤对象
userConfiguration.sayHi();
}
}
运行结果如下:
NOTE: 为什么要这么多类注解?
查看 @Controller / @Service / @Repository / @Configuration 等注解的源码发现:其实这些注解里面都有一个注解 @Component ,说明它们本身就是属于 @Component 的"子类"。@Component 是一个元注解,也就是说可以注解其他类注解,如 @Controller , @Service ,@Repository 等。 这些注解被称为 @Component 的衍生注解。@Controller , @Service 和 @Repository 用于 更具体的用例(分别在控制层, 业务逻辑层, 持久化层), 在开发过程中, 如果你要在业务逻辑层使用 @Component 或@Service,显然@Service是更好的选择。
@Component
public class BeanConfig {
@Bean
public User user(){
User user = new User();
user.setName("zhangsan");
user.setAge(18);
return user;
}
}
获取bean对象中的user:
@SpringBootApplication
public class SpringIocDemoApplication {
public static void main(String[] args) {
//获取Spring上下⽂对象
ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);
//从Spring上下⽂中获取对象
User user = context.getBean(User.class);
//使⽤对象
System.out.println(user);
}
}
运行结果如下:
@Component
public class BeanConfig {
@Bean
public User user1(){
User user = new User();
user.setName("zhangsan");
user.setAge(18);
return user;
}
@Bean
public User user2(){
User user = new User();
user.setName("lisi");
user.setAge(19);
return user;
}
}
@SpringBootApplication
public class SpringIocDemoApplication {
public static void main(String[] args) {
//获取Spring上下⽂对象
ApplicationContext context =
SpringApplication.run(SpringIocDemoApplication.class, args);
//根据bean名称, 从Spring上下⽂中获取对象
User user1 = (User) context.getBean("user1");
User user2 = (User) context.getBean("user2");
System.out.println(user1);
System.out.println(user2);
}
}
运行结果如下:
@Bean(name = {"u1","user1"})
public User user1(){
User user = new User();
user.setName("zhangsan");
user.setAge(18);
return user;
}
@SpringBootApplication
public class SpringIocDemoApplication {
public static void main(String[] args) {
//获取Spring上下⽂对象
ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);
//从Spring上下⽂中获取对象
User u1 = (User) context.getBean("u1");
//使⽤对象
System.out.println(u1);
}
}
@ComponentScan({"com.example.demo"})
@SpringBootApplication
public class SpringIocDemoApplication {
public static void main(String[] args) {
//获取Spring上下⽂对象
ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);
//从Spring上下⽂中获取对象
User u1 = (User) context.getBean("u1");
//使⽤对象
System.out.println(u1);
}
}
但是此做法不做推荐,那么推荐做法为: