想要将对象存储在 Spring 中,有两种注解类型可以实现:
1.类注解:@Controller【控制器】、@Service【服务】、@Repository【仓库】、@Component【组件】、@Configuration【配置】。
2.方法注解:@Bean。
接下来我们分别来看。
package com.beans;
import org.springframework.stereotype.Controller;
@Controller//将当前对象存储到spring中
public class UserController {
public void sayHi(String name){
System.out.println("你好,"+name);
}
}
使用之前读取对象的方式来读取上面的 UserController 对象:
import com.beans.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
// 1.获取 spring 上下文
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
// 2.得到 bean
UserController userController = context.getBean(UserController.class);
// 3.使用 bean
userController.sayHi("极致千叶");
}
}
注意事项1:即使在spring配置文件中配置了bean的扫描路径,但是5大类注解是不能省略的。
注意事项2:即使加了5大类注解,但类没有放在spring配置的bean路径下,那么也是不能将类注入到spring中的。
通常情况下‘是小驼峰(也就是将类名小写)就可以获取到bean对象
UserService userService=context.getBean("userService",UserService.class);
userService.sayHi("慕远笙歌");
如果第一个字母为大写,第二个字母为小写的情况下,那么bean的命名规则就是首字母小写。
如果第一个和第二个字母都是大写的情况下,那么bean命名规则是原类名
package com.beans;
import org.springframework.stereotype.Service;
@Service//将当前对象存储到spring中
public class UserService {
public void sayHi(String name) {
System.out.println("你好," + name);
}
}
import com.beans.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
// 1.获取 spring 上下文
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
UserService userService=context.getBean("userService",UserService.class);
userService.sayHi("慕远笙歌");
}
}
package com.beans;
import org.springframework.stereotype.Repository;
@Repository//将当前对象存储到spring中
public class UserRepository {
public void sayHi(String name) {
System.out.println("你好," + name);
}
}
import com.beans.UserRepository;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
// 1.获取 spring 上下文
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
UserRepository userRepository=context.getBean("userRepository", UserRepository.class);
userRepository.sayHi("谋长节短");
}
}
package com.beans;
import org.springframework.stereotype.Component;
@Component//将当前对象存储到spring中
public class UserComponent {
public void sayHi(String name) {
System.out.println("你好," + name);
}
}
import com.beans.UserComponent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
// 1.获取 spring 上下文
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
UserComponent userComponent=context.getBean("userComponent",UserComponent.class);
userComponent.sayHi("百战百胜");
}
}
package com.beans;
import org.springframework.context.annotation.Configuration;
@Configuration//将当前对象存储到spring中
public class UserConfiguration {
public void sayHi(String name) {
System.out.println("你好," + name);
}
}
import com.beans.UserConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
// 1.获取 spring 上下文
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
UserConfiguration userConfiguration=context.getBean("userConfiguration",UserConfiguration.class);
userConfiguration.sayHi("难知如阴");
}
}
类注解是添加到某个类上的,而方法注解是放到某个方法上的。
在 Spring 框架的设计中,方法注解 @Bean 要配合类注解才能将对象正常的存储到 Spring 容器中,如下代码所示:
package com.beans;
import com.model.User;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
@Controller
public class UserBeans {
@Bean//将当前方法返回的对象存储到spring中,默认bean名称为方法名
public User user1(){
User user=new User();
user.setId(1);
user.setName("极致千叶");
user.setPassword("123");
return user;
}
}
可以通过设置 name 属性给 Bean 对象进行重命名操作
package com.beans;
import com.model.User;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
@Controller
public class UserBeans {
//给当前对象起一个别名
@Bean(name="user2")//将当前方法返回的对象存储到spring中,默认bean名称为方法名
public User user1(){
User user=new User();
user.setId(1);
user.setName("极致千叶");
user.setPassword("123");
return user;
}
}
这个重命名的 name 其实是一个数组,一个 bean 可以有多个名字:
package com.beans;
import com.model.User;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
@Controller
public class UserBeans {
//给当前对象起一个或多个别名
@Bean(name={"user2","user"})//将当前方法返回的对象存储到spring中,默认bean名称为方法名
public User user1(){
User user=new User();
user.setId(1);
user.setName("极致千叶");
user.setPassword("123");
return user;
}
}
并且 name={} 可以省略,如下代码所示:
package com.beans;
import com.model.User;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
@Controller
public class UserBeans {
@Bean({"user2","user"})//将当前方法返回的对象存储到spring中,默认bean名称为方法名
public User user1(){
User user=new User();
user.setId(1);
user.setName("极致千叶");
user.setPassword("123");
return user;
}
}
当@Bean
重命名后,使用方法名不能获取到Bean对象!!!如果没有对Bean进行重命名,那么可以使用方法名获取Bean对象
获取 bean 对象也叫做对象装配,是把对象取出来放到某个类中,有时候也叫对象注入。
对象装配(对象注入)的实现方法以下 3 种:
属性注入是使用 @Autowired
实现的,将 Service 类注入到 Controller 类中。
Service 类的实现代码如下:
package com.beans;
import com.model.User;
import org.springframework.stereotype.Service;
@Service//将当前对象存储到spring中
public class UserService {
/**
* 根据id获取用户
* @param id
* @return
*/
public User getUserById(int id){
//伪代码
User user=new User();
user.setId(id);
user.setName("刑天");
user.setPassword("123");
return user;
}
}
Controller 类的实现代码如下:
package com.beans;
import com.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller//将当前对象存储到spring中
public class UserController {
//1.属性注入
@Autowired
private UserService userService;
public User getUserById(Integer id){
return userService.getUserById(id);
}
}
App方法:
import com.beans.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.beans.Introspector;
public class App {
public static void main(String[] args) {
// 1.获取 spring 上下文
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
UserController userController=context.getBean(UserController.class);
System.out.println(userController.getUserById(10));
}
}
构造方法注入是在类的构造方法中实现注入,如下代码所示:
package com.beans;
import com.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller//将当前对象存储到spring中
public class UserController2 {
private UserService userService;
//1.构造方法注入
@Autowired//如果当前类只有一个构造方法,那么@Autowired可以省略
public UserController2(UserService userService){
this.userService=userService;
}
public void sayHi(String name){
System.out.println("你好,"+name);
}
public User getUserById(Integer id){
return userService.getUserById(id);
}
}
如果当前类只有一个构造方法,那么@Autowired可以省略;但是如果当前方法中存在多个构造方法,那么@Autowired是不能省略的。
Setter 注入和属性的 Setter 方法实现类似,只不过在设置 set 方法的时候需要加上 @Autowired 注解,如下代码所示:
package com.beans;
import com.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller//将当前对象存储到spring中
public class UserController3 {
private UserService userService;
//3.Setter 注入
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
public void sayHi(String name){
System.out.println("你好,"+name);
}
public User getUserById(Integer id){
return userService.getUserById(id);
}
}
在进行类注入时,除了可以使用 @Autowired 关键字之外,我们还可以使用 @Resource 进行注入,如下代码所示:
package com.beans;
import com.model.User;
import org.springframework.stereotype.Controller;
import javax.annotation.Resource;
@Controller//将当前对象存储到spring中
public class UserController5 {
@Resource
private UserService userService;
// @Resource
public UserController5(UserService userService){
this.userService=userService;
}
public User getUserById(Integer id){
return userService.getUserById(id);
}
}
出身不同:@Autowired 来自于 Spring,而 @Resource 来自于 JDK 的注解;
使用时设置的参数不同:相比于 @Autowired 来说,@Resource 支持更多的参数设置,例如 name设置,根据名称获取 Bean。
支持的注入类型不同:@Autowired 支持属性注入、构造方法注入 和Setter 注入,@Resource 支持属性注入和 Setter 注入,不支持构造方法注入。
一个类型被注册到Spring多次时,程序运行就会出现异常。
package com.beans;
import com.model.User;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
@Controller
public class UserBeans {
// @Bean("user2")//将当前方法返回的对象存储到spring中,默认bean名称为方法名
@Bean(name="user1")
public User user1(){
User user=new User();
user.setId(1);
user.setName("极致千叶");
user.setPassword("123");
return user;
}
@Bean(name="user2")
public User user2(){
User user=new User();
user.setId(2);
user.setName("慕远笙歌");
user.setPassword("456");
return user;
}
}
解决异常的办法:
package com.beans;
import com.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import javax.annotation.Resource;
@Controller
public class UserController6 {
@Resource(name="user1")
private User user;
public void saiHi(){
System.out.println(user);
}
}
② 使用 @Qualifier(" ")
package com.beans;
import com.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import javax.annotation.Resource;
@Controller
public class UserController6 {
@Autowired
@Qualifier(value ="user2")
private User user;
public void saiHi(){
System.out.println(user);
}
}