认识Spring(下)
作者:~小明学编程
文章专栏:Spring框架
格言:热爱编程的,终将被编程所厚爱。
目录
Spring更加高效的读取和存储对象
存储bean对象
五大注解
关于五大类注解
对象的注入
属性注入
构造方法注入
Setter注入
三种注入方式的区别
@Resource 和 @Autowired 的区别
Bean的作用域和生命周期
Spring的执行流程
Bean的生命周期
Spring更加高效的读取和存储对象
存储bean对象
前面我们所介绍的方法过于的繁琐,我们可以通过注解来快速实现上述的功能。
<?xml version="1.0" encoding="UTF-8"?>
<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>
首先是我们所依赖的资源,其中com.beans是我们所要扫描的类的包。
五大注解
- Controller 控制器
- Service 服务
- Repository 仓库
- Configuration 配置
- Component 组件
利用上面这五大注解都可以完成我们对象的注入。
@Service
public class UserService {public void sayHi() {System.out.println("hi Service");}
}
@Repository
public class UserRepository {public void sayHi() {System.out.println("Hi Res");}
}
@Controller
public class UserController {public void sayHi() {System.out.println("hello");}
}
@Configuration
public class UserConfig {public void sayHi() {System.out.println("Hi Con");}
}
@Component
public class UserComponent {public void sayHi() {System.out.println("Hi Com");}
}
获取:
public static void main1(String[] args) {//1.获取上下文ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");//2.得到beanUserController userController = context.getBean("userController",UserController.class);userController.sayHi();UserService userService = context.getBean("userService",UserService.class);userService.sayHi();UserRepository userRepository = context.getBean("userRepository",UserRepository.class);userRepository.sayHi();UserConfig userConfig = context.getBean("userConfig",UserConfig.class);userConfig.sayHi();UserComponent userComponent = context.getBean("userComponent",UserComponent.class);userComponent.sayHi();}
获取的时候我们需要注意这个beanname,这个beanname是根据如下的逻辑。
关于五大类注解
既然我们五种注解的随便一种都能完成我们的对象的注入,那么我们为什么还是需要五种注解呢
因为我们一个软件是分为多个层面的,分为多层有助于我们的管理和控制。
Configuration 就是配置层:关于当前项目中的所有配置,都会写在这个文件夹里。
Controller 就是控制层:就是前端参数校验,主要就是校验前端数据的合理性和正确性。
Service 就是服务层,负责数据的组装和接口调用。更直白的说,服务器九四 “牵线搭桥” 让程序去调用对应的功能/接口/服务。
Repository 叫做仓库,但其实是 数据持久层,也叫做 Dao 层,就是对数据进行持久化操作(对数据库进行增删改查操作)。
我们使用不同的注解便于我们了解不同的代码的功能同时也方便我们对代码进行一个管理。
当然这五大类注解之间是有一定的关系的:
可以看到我们的configuration注解是调用了我们的component注解的,其它几个注解的实现方法也是如此,可以说我们的component注解是我们其它四大注解的一个父类。
对象的注入
前面我们了解了怎么样将对象给存储起来,也就是使用五大注解可以高效方便的将我们的对象给放在spring中,但是当我们想要使用的时候有没有什么方式可以比较高效的来使用呢,下面就介绍三种方式来实现我们对象的一个注入。
属性注入
通过 @Autowired 注入:
@Controller
public class UserController {@Autowiredprivate UserService userService;public void sayHi() {userService.sayHi();}
}
这里我们就通过关键字Autoeired的关键字来直接实现我们对象的一个注入,然在下面的方法之中我们就可以直接调用我们注入好的对象的方法了。
public static void main(String[] args) {//1.获取上下文ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");UserController userController = context.getBean(UserController.class);userController.sayHi();//hi Service}
构造方法注入
@Controller
public class UserController {
// @Autowiredprivate UserService userService;public UserController(UserService userService) {this.userService = userService;}public void sayHi() {userService.sayHi();}
}
这里我们可以直接通过构造方法的方式来进行对象的一个注入,但是值得我们注意的是,当我们的构造方法不止一个的时候就必须要使用Autowired关键字了,不然会报错。
@Controller
public class UserController {
// @Autowiredprivate UserService userService;@Autowiredpublic UserController(UserService userService) {this.userService = userService;}public UserController(UserService userService,int num) {this.userService = userService;}public void sayHi() {userService.sayHi();}
}
Setter注入
@Controller
public class UserController {private UserService userService;@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}public void sayHi() {userService.sayHi();}
}
同样我们也可以使用Setter这样一个方法来进行一个注入。
三种注入方式的区别
- 属性注入特点是写法简单,但是通用性不好,只能运行在 IoC 容器下,如果是 非 IoC 容器的话,就会出现问题。
- 构造方法注入,通用性更好。因为构造方法的优先级是最高的。确保使用注入对象之前,对象一定初始化过了。当构造方法注入参数太多时,就需要检查自己的代码是否符合单一设计原则的规范了。构造方法注入,也是 Spring 推荐的注入方法。
- Setter 注入是早期 Spring 版本推荐的写法,但是通用性没有构造方法注入通用,因为只有一个参数。
@Resource 和 @Autowired 的区别
相同点:都可以完成对象的注入。
不同点:
- 出身不同,@Resource 来自于 JDK,@Autowired 是由 Spring 框架提供的。
- @Autowired 支持属性注入,构造方法注入 和 Setter 注入,而 @Resource 不支持构造方法注入。
- 支持的参数不同:@Resource 支持更多的参数设置,比如 name、type 设置。而 @Autowired 只支持 required 参数设置。
Bean的作用域和生命周期
在我们使用bean的时候其实默认是用的同一个bean也就是说如果我们对其中的bean进行一个更改的话,那么当我们再次去使用这个bean此时依然是更改之后的bean。
@Component
public class UserBean {@Bean(name = {"user","user1"})
// @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)public User user2() {User user = new User(15,"lisi");return user;}@Bean(name = {"user2"})public User user1() {User user = new User(12,"zhangsan");return user;}
}
@Component
public class BeanScope1 {@Autowiredprivate User user2;public User getUser() {user2.setStr("aaa");return user2;}
}
@Component
public class BeanScope2 {@Autowiredprivate User user2;//user2必须事被注入过的public User getUser() {return user2;}
}
这个时候我们注入了两次bean对象,此时查看输入的结果:
public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");BeanScope1 beanScope1 = context.getBean(BeanScope1.class);System.out.println(beanScope1.getUser());BeanScope2 beanScope2 = context.getBean(BeanScope2.class);System.out.println(beanScope2.getUser());}
可以看到我们在对其进行更改之后,再次注入仍然是更改之后的User。
产生这样的原因是因为 Bean 在 Spring 中,默认情况下是单例状态,也就是所有人的使用都是同一个对像。这样可以很好的节约资源,避免资源的浪费。
Bean 的六种作用域
singleton:单例作用域(默认)在这种模式下的 Bean 在 IoC 容器里面,只存在一个实例。
prototype:原型作用域(多例模式)每次对作用域下的 Bean 请求,都会创建新的实例,然后再去获取 Bean。
request:请求作用域(Spring MVC)每次 Http 请求会创建新的 Bean 实例,类似于 prototype。
session:会话作用域(Spring MVC)在一个 http session 中,定义一个 Bean 实例。记录用户的登录信息。
application:全局作用域(Spring MVC)更多人使用的时候,就用 application。也是单例模式,应用在 Web 应用的上下文信息。
websocket:Http WebSocket 作用域(Spring WebSocket)在 WebSocket 会话中使用。
当我们想要改变其作用域的时候可以通过@Scope 的注解来进行改变
可以看到此时我们 所注入的对象就都是新的对象了。
设置作用域的时候,只需要通过 @Scope 注解就可以了:
- 直接设置值:@Scope(“prototype”)
- 使用枚举设置:@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
Spring的执行流程
1.我们首先是要启动我们的容器,去加载我们的配置文件。
也就是我们上面的这段代码。
2.接着就是根据我们的配置来完成我们的bean初始化。
通过扫描包中的spring注解。
3.注册 Bean 对象到容器中,只有在包扫描的路径上的类,且使用 Spring 的注解才可以被注册到容器当中。
4.装配 Bean 属性,也就是把 Bean 注册到其他类当中:
Bean的生命周期
Bean的生命周期就是Baen从诞生到销毁的一个过程 。
- 实例化 Bean(为 Bean 分配内存空间)
- 设置属性(Bean 注入和装配)
- Bean 初始化 a)执行各种通知(各种Aware)如:BeanNameAware,BeanFactoryAware,ApplicationContextAware 的接口方法。
b)执行 BeanPostProcessor 初始化前置方法。
c)执行 @PostConstruct 初始化方法,依赖注入操作之后被执行。
d)执行自己指定的 init-method 方法(如果有指定的话
e)执行 BeanPostProcessor 初始化后置方法。 - 使用 Bean
- 销毁 Bean,通过方法来销毁容器:如 @PreDestroy、DisposableBean、destroy-method
其大概的流程图就是这样的。
<?xml version="1.0" encoding="UTF-8"?>
<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><bean id="beanLife"class="com.beans.BeanLife" init-method="init"></bean>
</beans>
package com.beans;import org.springframework.beans.factory.BeanNameAware;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;/*** Created with IntelliJ IDEA.* Description:* User: 86184* Date: 2023-03-06* Time: 22:07*/
@Component
public class BeanLife implements BeanNameAware {@PostConstructpublic void Post() {System.out.println("PostConstruct");}@PreDestroypublic void Pre() {System.out.println("pre");}public void use() {System.out.println("use");}public void init() {System.out.println("init");}public void setBeanName(String s) {System.out.println("通知");}
}
执行流程如上。
认识Spring(下)相关推荐
- 解决Spring下无法实时访问本地静态资源
解决Spring下浏览器无法实时访问本地静态资源 场景1:原本地文件test.json中内容为 "1".我们通过前后端交互操作,修改test.json的内容为 "2&qu ...
- 哪些异常是RuntimeException?Sql异常属于RuntimeException吗?Spring下SQL异常事务回滚
哪些异常是RuntimeException?Sql异常属于RuntimeException吗?Spring下SQL异常事务回滚 参考文章: (1)哪些异常是RuntimeException?Sql异常 ...
- java webservice超时设置_[CXF]Spring下设置CXF的WebService客户端超时时长
评论 # re: [CXF]Spring下设置CXF的WebService客户端超时时长 2010-01-05 21:47 Emily32Av A kind of good information a ...
- Spring 下,关于动态数据源的事务问题的探讨
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 作者:青石路 cnblogs.com/youzhibing ...
- 如何看待Spring下单例模式与线程安全的矛盾
前言 有多少人在使用Spring框架时,很多时候不知道或者忽视了多线程的问题? 因为写程序时,或做单元测试时,很难有机会碰到多线程的问题,因为没有那么容易模拟多线程测试的环境.那么当多个线程调用同 ...
- mybatis整合spring下的的各种配置文件
1.applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <beans ...
- Java Web(5) Spring 下使用Junit4 单元测试
2019独角兽企业重金招聘Python工程师标准>>> 1. 如何在不启动Tomcat服务器的情况下对,Dao这些不依赖使用Servlet API的类来进行单元测试呢? 其实在Spr ...
- spring下jndi配置
参考: 1)Spring配置JNDI(Tomcat7) http://liuzidong.iteye.com/blog/962841 2)在tomcat 6.0下配置JNDI及在Spring中的使用 ...
- Spring下没有配置事务导致hibernate session报错
2019独角兽企业重金招聘Python工程师标准>>> org.hibernate.HibernateException: No Hibernate Session bound to ...
- hibernate自动建表到数据库及spring下自动建表到数据库
Hibernate支持自动建表,在开发阶段很方便,可以保证hbm与数据库表结构的自动同步. 如何使用呢?很简单,只要在hibernate.cfg.xml里加上如下代码 Xml代码<propert ...
最新文章
- TextView图文混排,显示添加的图片,三种常用方法,亲测
- 用微信小程序开发的Canvas绘制可配置的转盘抽奖
- 统计通话次数和时间的软件_通话时间统计app下载|通话时间统计安卓版下载 v1.0.3 - 跑跑车安卓网...
- python经典100例(21-40)
- 【论文写作】毕业论文写作套路之参考文献
- 程序自动化需要一个Windows服务
- iOS开发手记-仿QQ音乐播放器动态歌词的实现
- java4特征_java的四大基本特征
- 适配器模式C++实现
- 韩顺平html设计手册,韩顺平WEB前端网页设计视频教程
- Spring-全面详解(学习总结)
- cc2430的中文资料
- 如何只用电脑登录微信
- Three.js图像波动特效
- 【场景化解决方案】OA付款审批同步到金蝶KIS
- android将彩图转为黑白_android 将图片转换成黑白图片
- unity跳跃按钮_Unity——#04 跳跃
- WordPress活动日历和预订插件指南
- thx是什么意思_thx是什么意思?
- 格理论与密码学(二)
热门文章
- 如何把excel表格信息打印?轻松技巧!怎样打印excel表格文档数据?
- 持续集成Jenkins大法好
- 专利申请发明-发明专利的分类
- Python将多个单波段tif合并为一个影像
- 华硕路由ax86u 梅林_“亮眼”功能体验!华硕新品路由RT-AX86U评测
- 饮品自动贩卖机系统 c语言,自动贩卖机控制系统自动贩卖机控制系统.doc
- CAD中如何将默认保存格式为dxf格式?
- python批量处理excel提取包含指定关键字的行
- 交换式路由器与路由式交换机
- 【私有云架构】Openstack VS CloudStack:比较异同