Sping对象的存储和读取
创始人
2025-05-29 06:09:47
0

文章目录

  • 一、更简单的存储对象到Sping的实现步骤
    • 1.先创建一个Maven
    • 2. 添加Spring Maven核心包
    • 3.配置Spring xml 文件 ->配置Spring组件扫描路径(所有需要存储在Spring中的对象都需要放在此目录)
    • 4. 创建一个普通类,添加Main(作用:方便后面演示)
    • 5. 使用注解实现对象存储在Spring框架(类注解/方法注解)
      • @Controller 控制器 (对象存储)
      • @Service 业务逻辑类
      • @Repository[数据持久层](DAO)
      • @Component[组件类]
      • @Configuration[配置类]
      • @Bean
    • 6.使用方法注解 @Bean 将对象存储到 Spring
    • 7.@Bean起别名
    • 8.注解之间的关系
    • 9.Spring是如何生成出类注解 beanName的?
  • 二、更简单的从Spring获取对象(@Autowired )
    • 1. 属性注入
    • 2. Setter注入
    • 3. 构造方法注入
    • 三种注入方式的区别
  • 另外一种从Spring获取对象注解(@Resource )
    • 1.属性注入
    • 2. Setter注入
  • @Autowired 和 @Resource 关于注入对象名称的问题
      • @Autowired 和 @Resource 有什么区别?


一、更简单的存储对象到Sping的实现步骤

1.先创建一个Maven

在这里插入图片描述

2. 添加Spring Maven核心包

pom.xml中添加Spring的上下文和管理对象模块

org.springframeworkspring-context5.2.3.RELEASEorg.springframeworkspring-beans5.2.3.RELEASE

3.配置Spring xml 文件 ->配置Spring组件扫描路径(所有需要存储在Spring中的对象都需要放在此目录)

在resource目录下新建一个xml文件,并配置Spring组件的扫描路径

在这里插入图片描述
也就是说,只有在com.demo下的类才有可能被存储到Spring当中




4. 创建一个普通类,添加Main(作用:方便后面演示)

5. 使用注解实现对象存储在Spring框架(类注解/方法注解)

1.类注解:@Controller[控制器]、@Service[业务逻辑类]、@Repository[数据持久类]、@Component[组件类]、@Configuration[配置类]
2.方法注解:@Bean
在这里插入图片描述

@Controller 控制器 (对象存储)

@Controller // 将当前的类存储到 Spring 中
public class UserController {/*** 对象中的测试方法* @param name*/public void testHello(String name) {System.out.println("hello Controller " + name);}
}

注意事项:

  1. 读取存入对象的id:默认情况下就是首字母小写

在这里插入图片描述

  1. 所有需要存储到 Spring框架中的对象的目录,必须在Spring 配置的目录下,conmponent-scan

在这里插入图片描述

@Service 业务逻辑类

@Service //将当前对象存储到 Spring 当中
public class UserService {public void printService(String name) {System.out.println("hello Service "+name);}
}

@Repository[数据持久层](DAO)

@Repository // 将对象存储到 Spring中
public class UserRepository {public void printRepository(String name) {System.out.println("hello repository "+name);}
}

@Component[组件类]

@Component //将对象存储到Spring中
public class UserComponent {public void printComponent(String name) {System.out.println("hello component "+name);}
}

@Configuration[配置类]

@Configuration // 将对象存储到Spring中
public class UserConfiguration {public void printConfiguration(String name) {System.out.println("hello Configuration "+name);}
}

@Bean

@Bean方法注解,可以把方法返回的对象注入到Spring中

public static void main(String[] args) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");//  得到 controller 对象UserController controller = applicationContext.getBean("userController",UserController.class);controller.printController("控制器");// 得到 service 对象UserService service = applicationContext.getBean("userService",UserService.class);service.printService("业务逻辑");// 得到 repository对象UserRepository repository = applicationContext.getBean("userRepository",UserRepository.class);repository.printRepository("数据持久DAO");// 得到 configurationUserConfiguration configuration = applicationContext.getBean("userConfiguration",UserConfiguration.class);configuration.printConfiguration("配置类");// 得到 componentUserComponent component = applicationContext.getBean("userComponent",UserComponent.class);component.printComponent("组件类");}

6.使用方法注解 @Bean 将对象存储到 Spring

注意事项:Spring 默认情况下是类扫描,因此如果使用的是方法注解 @Bean,那么必须要配合类注解(@Component)一起使用(也可以是其它注解),才能将方法返回对象顺利存储到 Spring中

@Component
public class UserBean {@Beanpublic User user() {//伪代码//查询数据库获取对象User user = new User();user.setId(1);user.setName("张三");user.setAge(20);return user;}
}

获取对象

public class App {public static void main(String[] args) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");//通过 @Bean注解获取对象User user = applicationContext.getBean("user",User.class);System.out.println(user);}
}

7.@Bean起别名

注意:如果给@Bean起别名后,就只能用别名来获取对象了

@Component
public class UserBean {@Bean(name = {"getUser"})public User user() {//伪代码//查询数据库获取对象User user = new User();user.setId(1);user.setName("张三");user.setAge(20);return user;}
}

获取对象

public class App {public static void main(String[] args) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");//通过 @Bean注解获取对象User user = applicationContext.getBean("getUser",User.class);System.out.println(user);}
}

@Bean还可以起多个别名

@Component
public class UserBean {@Bean(name = {"getUser","myUser"})public User user() {//伪代码//查询数据库获取对象User user = new User();user.setId(1);user.setName("张三");user.setAge(20);return user;}}

并且 nume = 可以省略

@Bean({"getUser","myUser"})public User user() {//伪代码//查询数据库获取对象User user = new User();user.setId(1);user.setName("张三");user.setAge(20);return user;}

8.注解之间的关系

为啥要有那么多注解,就是让程序员看到类注解之后,就能直接了解当前类的⽤途

通过源码可以发现,@controller/@Service/@Repository/@Configuration
这四个注解从业务逻辑来说,可以认为这四个注解是 @Component的子类

在这里插入图片描述

9.Spring是如何生成出类注解 beanName的?

查看 AnnotationBeanNameGenerator 中的源码
AnnotationBeanNameGenerator -> buildDefaultBeanName -> Introspector.decapitalize(shortClassName)

如果类名的长度大于1,并且第一个和第二个字母都是大写就直接返回
否则就把类名的第一个字母改为小写直接返回

在这里插入图片描述

二、更简单的从Spring获取对象(@Autowired )

从Spring中获取对象的手段:

  1. 属性注入(属性注册)UserController ——> UserService
  2. Setter 注入
  3. 构造方法注入
@Service //将当前对象存储到 Spring 当中
public class UserService {/*** 通过用户Id查询用户* @param id* @return*/public User findUserById(int id) {// 伪查询,不连接sqlUser user = new User();if (id == 1) {user.setId(1);user.setName("张三");user.setAge(18);} else {user.setId(2);user.setName("李四");user.setAge(20);}return user;}
}

1. 属性注入

属性注⼊是使⽤ @Autowired 实现的,将 UserService 类注⼊到 Controller 类中

@Controller // 将当前的类存储到 Spring 中
public class UserController {// 属性注入(属性注册), 从Spring中取出对象,注入到当前类中@Autowiredprivate UserService userService;public User findUserById(Integer id) {if (id == null) {// 如果是无效参数return new User();}return userService.findUserById(id);}
}

2. Setter注入

注意:必须在 Setter方法上加上 @Autowired 注解,不然会注入失败。又因为spring是类扫描的,所以要在当前类上加上对应注解,该对象才有可能存入 spring 中

@Controller
public class UserController2 {private UserService userService;public User findUserById(Integer id) {if (id == null) {return new User();}return userService.findUserById(id);}// Setter注入@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}
}

3. 构造方法注入

注意:如果类中只有一个构造方法,@Autowired注解可以省略

@Controller
public class UserController3 {private UserService userService;//通过构造方法注入,若果只是存在一个构造方法,那么@Autowired可以省略@Autowiredpublic UserController3(UserService userService) {this.userService = userService;}public UserController3(String name) {System.out.println(name);}public User findUserById(Integer id) {if (id == null) {//判断id合法return new User();}return userService.findUserById(id);}
}

三种方式的getBean实现

public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");// 方法1: 属性注入UserController userController = (UserController) context.getBean("userController");System.out.println(userController.findUserById(2));// 方法2: Setter注入UserController2 userController2 = context.getBean("userController2",UserController2.class);System.out.println(userController2.findUserById(1));// 方法3: 构造方法注入UserController3 userController3 = context.getBean("userController3",UserController3.class);System.out.println(userController3.findUserById(2));}

三种注入方式的区别

  • 属性注入的优点,使用方便;缺点是只能用于 Ioc容器,如果不是IoC容器就无法使用,并且只有在使用的时候才会出现 空指针异常
  • 构造方法注入是 Spring官方推荐的注入方式,它的缺点是如果有多个注入会显得比较臃肿,但出现这种情况你应该考虑一下当前类是否符合程序的单一职责的设计模式了,它的优点是通用性,在使用之前一定能保证注入的类不为空
  • Setter方式是Spring前期版本推荐的注入方式,但通用性不如构造方法,所以Spring先版本已经推荐使用构造方法注入的范式来进行类注入了

另外一种从Spring获取对象注解(@Resource )

@Resource 和 @Autowired 注解的使用方式非常类似

1.属性注入

@Controller
public class UserController4 {@Resourceprivate UserService userService;public User findUserById(Integer id) {if (id == null) {return new User();}return userService.findUserById(id);}
}

2. Setter注入

@Controller
public class UserController5 {private UserService userService;public User findUserById(Integer id) {if (id == null) {return new User();}return userService.findUserById(id);}@Resourcepublic void setUserService(UserService userService) {this.userService = userService;}
}

注意:@Resource不能通过构造方法注入对象

在这里插入图片描述

@Autowired 和 @Resource 关于注入对象名称的问题

@Autowired 和 @Resource 它们都是做了两手准备,它们会先从 一种类型进行选择,比如先从名称(ByName)进行获取Bean对象,如果根据名称获取不到,此时根据另一种类型(ByType)获取(根据名称或者类型获取

如果Bean对象只有一个的时候,注入对象名就无所谓了

在这里插入图片描述

问题来了:如果注入的名称是不存在的,并且类型有多个,那么注入就会失败

@Component
public class UserBean {@Beanpublic User getUser1() {User user = new User();user.setId(1);user.setName("张三");user.setAge(22);return user;}@Beanpublic User getUser2() {User user = new User();user.setId(2);user.setName("李四");user.setAge(20);return user;}
}

注入代码

@Service
public class UserService {@Resourceprivate User user;public User findUserById(int id) {User user = new User();if (id == 1) {user.setId(1);user.setName("张三");user.setAge(18);} else {user.setId(2);user.setName("李四");user.setAge(20);}return user;}
}

运行就会报错,因为这里名字不存在,并且有多个类型注入

同⼀类型多个 Bean 报错处理,可以为Bean重命名,再通过重命名的名字注入Bean对象

  1. 使用 @Resource(name=“指定bean名称”)
    加上 name 说明加载的时候是用 beanName加载的
@Service
public class UserService {@Resource(name = "getUser1")private User user;public User findUserById(int id) {User user = new User();if (id == 1) {user.setId(1);user.setName("张三");user.setAge(18);} else {user.setId(2);user.setName("李四");user.setAge(20);}return user;}
}

在这里插入图片描述
2.使用注入注解配合@Qualifier来进行解决

@Service
public class UserService {@Autowired@Qualifier(value = "getUser2")private User user;public User findUserById(int id) {User user = new User();if (id == 1) {user.setId(1);user.setName("张三");user.setAge(18);} else {user.setId(2);user.setName("李四");user.setAge(20);}return user;}
}

在这里插入图片描述

@Autowired 和 @Resource 有什么区别?

  1. 出身不同,@Autowired 来自于 Spring 框架,而 @Resource来自于 JDK
  2. 作用于不同,使用@Autowired可以进行 属性注入、Setter注入、构造器注入;而 @Resource只能进行 属性注入和Setter注入。
  3. 功能不同,@Resource可以配合更多属性进行使用,而 @Autowired 支持的属性较少,比如 @Resource 可以 配合 name 属性进行使用,从而完成对象的别名注入

相关内容

热门资讯

企业IP打造指南:小公司低成本... 小公司做企业IP,不是为了装门面,而是让客户在没见到你之前,就能通过内容知道你是谁、你解决什么问题、...
官方:赵心童入选世界斯诺克名人... 北京时间5月8日消息,世界斯诺克巡回赛(WST)今日正式公布了2025/26赛季年终奖项及名人堂更新...
小灰熊AI学员王锋:希望能跟上... 35了,老程序员了。 从进入互联网行业到现在,其实已经做了很多年移动端开发。最早那几年,安卓行业发展...
原创 2... 2026年全国两会把稳定房地产市场列为重点工作,政府工作报告明确提出因城施策控增量、去库存、优供给。...
一年翻倍,六年未归——徽商银行... 文:向善财经 今年的港股市场,与A股市场出现了明显的分化。 A股这边,科技板块在AI浪潮中热闹非凡;...
古井贡酒2025:在行业深度调... 以“稳”为底、以“新”为翼。 文/每日财报 杜康 在行业库存高企、价格倒挂的背景下,当多数酒企在为...
好上好8408万收购鼎瑞芯加码... 5月7日晚,好上好(001298.SZ)抛出一份收购公告,拟以8408万元现金收购深圳市鼎瑞芯科技有...
全面大撤离!李嘉诚英国“套现”... 突发,李嘉诚又卖了。 这次,套现了455亿。 金额不少,但更值得关注的是透露着不同寻常的信号。 因为...
油气价格上涨加剧法国一季度贸易... 据新华社,法国海关7日发布的数据显示,受中东局势推高国际油气价格影响,法国今年第一季度贸易逆差扩大至...
昆仑芯启动科创板IPO上市辅导... 5月8日,据证监会官网显示,昆仑芯(北京)科技股份有限公司于2026年5月7日正式启动科创板上市辅导...
贵州茅台酒股份有限公司关于回购... 来源:上海证券报 证券代码:600519 证券简称:贵州茅台 公告编号:临2026-016 贵州茅...
百度昆仑芯启动科创板上市辅导,... 5月8日,证监会官网显示,昆仑芯(北京)科技股份有限公司 (下称“昆仑芯”)于2026年5月7日正式...
滕州信华的承压时刻:罚单、失信... 2026年4月末,滕州信华美元债单日跌近2%,关联方被列“老赖”。半年前,这家AA+城投曾因非市场化...
002808,或被终止上市! 【导读】因触及财务类退市指标,*ST恒久或被终止上市 中国基金报记者 李智 又一A股或被终止上市。 ...
院士团队掌舵,溧阳这家企业已完... 近日,溧阳天目先导电池材料科技有限公司(下称“天目先导”)官宣完成B轮融资,投资方包括知卓创新资本、...
工商银行全新推出“工盈研选”品... 深圳商报·读创客户端记者 詹钰叶 近日,工商银行重磅推出「工盈研选」基金销售服务品牌,以客户盈利为核...
和讯信息胡云龙:逼空走势,周五... 今天市场出现逼空走势,场内投资者因持有筹码而尤为受益。五一前布局的投资者当前收获颇丰。然而,随着上证...
今晚,油价上调! 4月21日国内成品油价格下调以来,国际市场原油价格剧烈震荡,前期大幅上涨后近日有所回落,本次调价的前...
南方东英旗下两倍做多海力士,成... 【导读】南方东英旗下两倍做多海力士,成为全球最大的个股杠杆及反向产品 中国基金报记者 伊万 人工智能...
原创 金... 黄金,这东西从古至今就没离开过中国人的生活。从老辈人压箱底的小黄鱼,到如今年轻人结婚绕不开的“三金”...