上篇文章中我们详细的讲解了Spring对象的存取和使用,感兴趣的朋友可以去看上篇文章Spring的创建和使用,但是上篇文章中讲的存取对象的方法相对来说有些繁琐,这篇文章我们就介绍使用注解的方式来进行存储对象吧~~
这里说的配置扫描路径的方式就是在spring的配置文件中配置一下存储对象的包的路径,只有被配置的包下的所有类,添加了注解才能被识别并注册到Spring中。
试想一下,如果不配置路径,那么较大的项目中有成百上千个类,那么就要一个一个类挨着扫描,性能很低。
在配置文件中添加:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:content="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<content:component-scan base-package="com.beans">content:component-scan>
beans>
配置好扫描路径后,就可以通过添加注解将对象存储在Spring中,有以下两种注解类型:
注意事项:
使用@Controller存储bean:
@Controller
public class UserController {
public void sayHi(String name){
System.out.println("Hi "+name);
}
}
使用之前的方式获取UserController对象:
/**
* 启动类
*/
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("java");
}
}
使用@Service存储bean:
@Service //将当前bean对象存储到spring中
public class UserService {
public void sayHi(String name){
System.out.println("Hi "+name);
}
}
使用之前的方式获取UserService 对象:
/**
* 启动类
*/
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("javaee");
}
}
使用@Repository存储bean:
@Repository //将对象注入到spring中
public class UserRepository {
public void sayHello(String name){
System.out.println("Hello "+name);
}
}
使用之前的方式获取UserRepository 对象:
/**
* 启动类
*/
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.sayHello("世界");
}
}
使用@Component存储bean:
@Component //将对象注入到spring中
public class UserComponent {
public void sayHello(String name){
System.out.println("Hello "+name);
}
}
使用之前的方式获取UserComponent 对象:
/**
* 启动类
*/
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.sayHello("world");
}
}
使用@Configuration存储bean:
@Configuration //将对象注入到spring中
public class UserConfiguration {
public void sayHello(String name){
System.out.println("Hello "+name);
}
}
使用之前的方式获取UserConfiguration 对象:
/**
* 启动类
*/
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.sayHello("world");
}
}
我们来看一下除了Component之外其他四个类注解的源码,不难发现,他们都是依靠@Component实现的,因此可以说@Component式其他四个类注解的父类。
那么这些类的功能都相同,为什么还要有这么多类注解呢?
其实就像我们国家的车牌一样,会根据省份进行划分,省份会进一步根据省内的城市进行划分,这样交警叔叔在看到车牌号后,一下就可以辨别这个车是哪个省哪个城市的车。
那么spring中的类注解也是同样的道理,就是通过这些注解来对我们的工程进行分层,每个注解代表不同的用途,那么这样当程序员一看到这个注解就知道这个类是用来做什么的。
2.类名的首字母和第二个字母都是大写,则在读取的时候使用原类名。
这是为什么呢?
我们就要来看看bean命名规则的源码:
它使用了JDK中的decapitalize方法:
public static String decapitalize(String name) {
if (name == null || name.length() == 0) {
return name;
}
if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
Character.isUpperCase(name.charAt(0))){
return name;
}
char chars[] = name.toCharArray();
chars[0] = Character.toLowerCase(chars[0]);
return new String(chars);
}
这个方法很清晰的说明了命名规则,就是我们上面提到的两种。
注意~~
方法注解必须配合五大类注解其中之一进行使用才有效,否则无效。
@Component
public class UserBeans {
@Bean //将当前方法返回的对象存储到spring中,默认bean是方法名
public User getUser(){
User user=new User();
user.setId(1);
user.setName("张三");
user.setPassword("123456");
return user;
}
}
/**
* 启动类
*/
public class App {
public static void main(String[] args) {
//1.获取Spring上下文
ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
User user1=context.getBean("getUser",User.class);
System.out.println(user1);
}
}
@Component
public class UserBeans {
@Bean(name="user1") //将当前方法返回的对象存储到spring中,默认bean是方法名
public User getUser(){
User user=new User();
user.setId(1);
user.setName("张三");
user.setPassword("123456");
return user;
}
}
/**
* 启动类
*/
public class App {
public static void main(String[] args) {
//1.获取Spring上下文
ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
User user1=context.getBean("user1",User.class);
System.out.println(user1);
}
}
在对Bean进行重命名之后,就不可以使用原来的类名首字母小写和方法名进行获取对象。
存储完对象,就可以来取对象了。
获取对象又叫也叫做对象装配,是把对象取出来放到某个类中,也叫对象注入。
分为以下三种注入方式:
以下注入方式的演示,都是将Service注入到Controller类中。
属性注入就是在属性上加上@Autowired,将Service注入到Controller类中。
Service类实现:
@Service //将当前bean对象存储到spring中
public class UserService {
public void sayHi(String name){
System.out.println("Hi "+name);
}
/**
* 根据id获取用户
* @param id
* @return
*/
public User getUserById(int id){
//伪代码
User user=new User();
user.setId(id);
user.setName("雪雪");
user.setPassword("1234");
return user;
}
}
Controller类:
@Controller
public class UserController {
//1.属性注入
@Autowired
private UserService userService;
public void sayHi(String name){
System.out.println("Hi "+name);
}
public User getUserId(Integer id){
//伪代码
return userService.getUserById(id);
}
}
获取Controller中的getUserId的方法:
/**
* 启动类
*/
public class App {
public static void main(String[] args) {
//1.获取Spring上下文
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml")
UserController userController = context.getBean("userController",UserController.class);
System.out.println(userController.getUserId(10));
}
}
@Controller
public class UserController2 {
private UserService userService;
//2.构造方法注入
@Autowired
public UserController2(UserService userService){
this.userService=userService;
}
public void sayHi(String name){
System.out.println("Hi "+name);
}
public User getUserId(Integer id){
//伪代码
return userService.getUserById(id);
}
}
注意:如果当前类中只有一个构造方法,那么不加@Autowied注解也是可以获取到User对象,但是如果有多个构造方法,那就必须加@Autowied注解。
@Controller
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("Hi "+name);
}
public User getUserId(Integer id){
//伪代码
return userService.getUserById(id);
}
}
在进行获取对象时,除了可以使用@Autowired注解外,还可以使用@Resource注解。
@Controller
public class UserController5 {
private UserService userService;
@Resource
public void setUserService(UserService userService) {
this.userService = userService;
}
public void sayHi(String name){
System.out.println("Hi "+name);
}
public User getUserId(Integer id){
//伪代码
return userService.getUserById(id);
}
}
@Component
public class UserBeans {
@Bean(name="user1") //将当前方法返回的对象存储到spring中,默认bean是方法名
public User getUser(){
User user=new User();
user.setId(1);
user.setName("张三");
user.setPassword("123456");
return user;
}
@Bean(name="user2")
public User getUser2(){
User user=new User();
user.setId(2);
user.setName("李四");
user.setPassword("456");
return user;
}
}
@Controller
public class UserController6 {
@Resource
private User user;
public void sayHi(){
System.out.println(user);
}
}
怎么解决呢?
@Controller
public class UserController6 {
@Resource(name="user2")
private User user;
public void sayHi(){
System.out.println(user);
}
}
@Controller
public class UserController6 {
@Autowired
@Qualifier(value="user1")
private User user;
public void sayHi(){
System.out.println(user);
}
}