顶层大纲
JDBC
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0f2vudxM-1663638076790)(/Users/huijia/Library/Containers/com.tencent.xinWeChat/Data/Library/Application Support/com.tencent.xinWeChat/2.0b4.0.9/faf9f9db825adc1de526cb82984347c8/Message/MessageTemp/9e20f478899dc29eb19741386f9343c8/Image/1821659949665_.pic.jpg)]
jdbc.properites
user=root
password=yl20000304@
url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false
driverClass=com.mysql.cj.jdbc.Driver
通用的数据库连接JDBCUtils
public class JDBCUtils {
/*获取数据库的连接*/
public static Connection getConnection() throws Exception{
//1读取配置文件中的4个基本信息
InputStream inputStream =
ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properites");
Properties pros = new Properties();
pros.load(inputStream);
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverClass");
// 2加载驱动
Class.forName(driverClass);
//3获取连接
Connection connection = null;
connection = DriverManager.getConnection(url, user, password);
return connection;
}
public static void closeResource(Connection conn, Statement ps) {
//资源关闭
try {
if(ps != null)
ps.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if(conn != null)
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
public static void closeResource(Connection conn, Statement ps, ResultSet rs) {
//资源关闭
try {
if(ps != null)
ps.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if(conn != null)
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if(rs != null)
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
javaBean (User表)
import java.sql.Date;
/*ORM编程思想 (object relational mapping)
* 一个数据表对应一个java类
* 表中的一条记录对应java类的一个对象
* 表中的一个字段对应java类的一个属性*/
public class User {
private int id;
private String username;
private String password;
private Date birth;
private String email;
public User(int id, String username, String password, Date birth, String email) {
this.id = id;
this.username = username;
this.password = password;
this.birth = birth;
this.email = email;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", brith=" + birth +
", email='" + email + '\'' +
'}';
}
public User() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
##通用的增删改操作
//通用的增删改操作
public void update(String sql, Object... args) throws Exception {
Connection connection = null;
PreparedStatement ps = null;
try {
//获取连接
connection = JDBCUtils.getConnection();
//预编译
ps = connection.prepareStatement(sql);
//填充占位符
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
//执行sql
ps.execute();
} catch (Exception e) {
e.printStackTrace();
}finally {
//关闭资源
JDBCUtils.closeResource(connection, ps);
}
}
针对Department表做通用的查询操作
public Department CommonQuery(String sql, Object... args) throws Exception {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConnection();
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
//执行,获取结果集
rs = ps.executeQuery();
// 获取元数据
ResultSetMetaData rsmd = rs.getMetaData();
//获取列数
int columnCount = rsmd.getColumnCount();
if (rs.next()) {
Department department = new Department();
for (int i = 0; i < columnCount; i++) {
//获取每个列的值,通过RestSet
Object columnValue = rs.getObject(i + 1);
//获取列的列名
//String columnName = rsmd.getColumnName(i + 1);
// 获取列的别名 针对于表的字段名与类的属性名不相同的情况下使用
String columnLabel = rsmd.getColumnLabel(i + 1);
//反射,将指定columnName的属性赋值为columnValue
Field field = Department.class.getDeclaredField(columnLabel);
//设置访问私有属性的权限
field.setAccessible(true);
field.set(department, columnValue);
}
return department;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn, ps, rs);
}
return null;
}
针对不同表的通用查询操作(单条记录)
public <T> List<T> getForList(Class<T> tClass, String sql, Object... args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConnection();
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
//执行,获取结果集
rs = ps.executeQuery();
// 获取元数据
ResultSetMetaData rsmd = rs.getMetaData();
//获取列数
int columnCount = rsmd.getColumnCount();
// 创建集合对象
ArrayList<T> list = new ArrayList<>();
while (rs.next()) {
T t = tClass.newInstance();
for (int i = 0; i < columnCount; i++) {
//获取每个列的值,通过RestSet
Object columnValue = rs.getObject(i + 1);
//获取列的列名
String columnName = rsmd.getColumnName(i + 1);
// 获取列的别名 针对于表的字段名与类的属性名不相同的情况下使用
String columnLabel = rsmd.getColumnLabel(i + 1);
//反射,将指定columnName的属性赋值为columnValue
Field field = tClass.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(t, columnValue);
}
list.add(t);
}
return list;
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn, ps, rs);
}
return null;
}
针对不同表的通用查询操作(多条记录)
public <T> List<T> getForList(Class<T> tClass, String sql, Object... args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConnection();
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
//执行,获取结果集
rs = ps.executeQuery();
// 获取元数据
ResultSetMetaData rsmd = rs.getMetaData();
//获取列数
int columnCount = rsmd.getColumnCount();
// 创建集合对象
ArrayList<T> list = new ArrayList<>();
while (rs.next()) {
T t = tClass.newInstance();
for (int i = 0; i < columnCount; i++) {
//获取每个列的值,通过RestSet
Object columnValue = rs.getObject(i + 1);
//获取列的列名
String columnName = rsmd.getColumnName(i + 1);
// 获取列的别名 针对于表的字段名与类的属性名不相同的情况下使用
String columnLabel = rsmd.getColumnLabel(i + 1);
//反射,将指定columnName的属性赋值为columnValue
Field field = tClass.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(t, columnValue);
}
list.add(t);
}
return list;
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn, ps, rs);
}
return null;
}
PreparedStatement & Statement
- PreparedStatement可以解决sql注入的问题
- PreparedStatement解决拼串的问题
- PreparedStatement可以操作Blob的数据,Statement则解决不了
- PreparedStatement可以实现更高效的批量插入
- 用PreparedStatement就对了
批量添加
/*使用PreparedStatement实现批量数据的操作
* update、delete本身具有批量操作的效果
* 此时的批量操作指的是批量插入
*
* */
法一:7997
@Test
public void insetTest() throws Exception {
Connection conn = null;
PreparedStatement ps = null;
try {
conn = JDBCUtils.getConnection();
String sql = "insert into t_test(name) values(?)";
ps = conn.prepareStatement(sql);
long start = System.currentTimeMillis();
for (int i = 1; i <= 20000; i++) {
ps.setObject(1, "name" + i);
ps.execute();
}
long end = System.currentTimeMillis();
System.out.println("插入的时间是:" + (end - start));
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn, ps);
}
}//7997
法二:
//6778
@Test
public void insetTest2() throws Exception {
Connection conn = null;
PreparedStatement ps = null;
try {
conn = JDBCUtils.getConnection();
String sql = "insert into t_test(name) values(?)";
ps = conn.prepareStatement(sql);
long start = System.currentTimeMillis();
for (int i = 1; i <= 20000; i++) {
ps.setObject(1, "name" + i);
//积攒sql
ps.addBatch();
if (i % 500 == 0) {
//执行batch
ps.executeBatch();
//清空batch
ps.clearBatch();
}
}
long end = System.currentTimeMillis();
System.out.println("插入的时间是:" + (end - start));
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn, ps);
}
}
法三:
//2163
@Test
public void insetTest3() throws Exception {
Connection conn = null;
PreparedStatement ps = null;
try {
conn = JDBCUtils.getConnection();
//设置不允许自动提交数据
conn.setAutoCommit(false);
String sql = "insert into t_test(name) values(?)";
ps = conn.prepareStatement(sql);
long start = System.currentTimeMillis();
for (int i = 1; i <= 20000; i++) {
ps.setObject(1, "name" + i);
//积攒sql
ps.addBatch();
if (i % 500 == 0) {
//执行batch
ps.executeBatch();
//清空batch
ps.clearBatch();
}
}
//提交数据
conn.commit();
long end = System.currentTimeMillis();
System.out.println("插入的时间是:" + (end - start));
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn, ps);
}
}
execute()&executeUpdate()
//ps.execute();如果执行的是查询操作,有返回结果,则此方法返回true
//如果执行的是增删改操作,没有返回结果,则此方法为false
executeUpdate()返回修改的记录数
Mysql的Blob类型
- Blob是一个二进制大型对象,是一个可以存储大量数据的容器,可以容纳不同大小的数据
- 插入Blob类型的数据必须使用PreparedStatement,因为Blob类型的数据无法使用字符串拼接
- mysql的四种Blob类型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xFRYLltV-1663638076790)(/Users/huijia/Library/Application Support/typora-user-images/image-20220811152231873.png)]
- 实际使用中根据需要存入的数据大小定义不同的Blob类型
- 如果存储的文件过大,性能会降低
@Test
public void TestQuery() {
Connection conn = null;
PreparedStatement ps = null;
ResultSet resultSet = null;
InputStream is = null;
FileOutputStream fos = null;
try {
conn = JDBCUtils.getConnection();
String sql = "SELECT id,username,password,birth,email, photo from t_user WHERE id=?";
ps = conn.prepareStatement(sql);
ps.setObject(1, 5);
resultSet = ps.executeQuery();
if (resultSet.next()) {
// int id = resultSet.getInt(1);
// String username = resultSet.getString(2);
// String password = resultSet.getString(3);
// Date birth = resultSet.getDate(4);
// String email = resultSet.getString(5);
int id = resultSet.getInt("id");
String username = resultSet.getString("username");
String password = resultSet.getString("password");
Date birth = resultSet.getDate("birth");
String email = resultSet.getString("email");
User user = new User(id, username, password, birth, email);
System.out.println(user);
Blob photo = resultSet.getBlob("photo");
is = photo.getBinaryStream();
fos = new FileOutputStream("test.jpg");
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭资源
JDBCUtils.closeResource(conn, ps, resultSet);
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void testInsert() throws Exception {
Connection conn = JDBCUtils.getConnection();
String sql = "insert into t_user (username,password,birth,email,photo) values(?,?,?,?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setObject(1, "赵匡义");
ps.setObject(2, "12esdfsddj");
ps.setObject(3, "201-02-23");
ps.setObject(4, "fdsjfkdsfsdjd@gmail.com");
FileInputStream is = new FileInputStream(new File("IMG_0823.jpeg"));
ps.setBlob(5, is);
ps.execute();
JDBCUtils.closeResource(conn, ps);
}
事务
概念
数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。
特性(ACID)
数据库如果支持事务的操作,那么就具备以下四个特性:
1、原子性(Atomicity)
事务是数据库的逻辑工作单位,事务中包括的诸操作要么全做,要么全不做。
2、一致性(Consistency)
事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
3、隔离性(Isolation)
一个事务的执行不能被其他事务干扰。
4、持续性/永久性(Durability)
一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。
mysql的四种隔离级别
SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。
Read Uncommitted(读取未提交内容)
在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。
Read Committed(读取提交内容)
这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。
Repeatable Read(可重读)
这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。
Serializable(可串行化)
这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
这四种隔离级别采取不同的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。例如:
脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。
不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。
幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FN4WMjvu-1663638076791)(/Users/huijia/Library/Application Support/typora-user-images/image-20220812181715486.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kjZ2A1qN-1663638076791)(/Users/huijia/Library/Application Support/typora-user-images/image-20220813094905695.png)]
作者:游泳的石头
链接:https://www.jianshu.com/p/8d735db9c2c0
功能
1、实现数据共享:数据共享包含所有用户可同时存取数据库中的数据,也包括用户可以用各种方式通过接口使用数据库,并提供数据共享。
2、减少数据的冗余度:同文件系统相比,由于数据库实现了数据共享,从而避免了用户各自建立应用文件。减少了大量重复数据,减少了数据冗余,维护了数据的一致性。
3、保持数据的独立性:数据的独立性包括逻辑独立性(数据库中数据库的逻辑结构和应用程序相互独立)和物理独立性(数据物理结构的变化不影响数据的逻辑结构)。
4、数据实现集中控制:文件管理方式中,数据处于一种分散的状态,不同的用户或同一用户在不同处理中其文件之间毫无关系。利用数据库可对数据进行集中控制和管理,并通过数据模型表示各种数据的组织以及数据间的联系。
5、数据一致性和可维护性,以确保数据的安全性和可靠性:主要包括:安全性控制、完整性控制、并发控制,使在同一时间周期内,允许对数据实现多路存取,又能防止用户之间的不正常交互作用。
代码实现
//事务的实现
public int update2(Connection conn, String sql, Object... args) {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
// ps.execute(); //ps.execute();如果执行的是查询操作,有返回结果,则此方法返回true
//如果执行的是增删改操作,没有返回结果,则此方法为false
return ps.executeUpdate();//返回修改的记录数
//
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(null, ps);
}
return 0;
}
@Test
public void update2Test() throws Exception {
Connection conn = null;
try {
conn = JDBCUtils.getConnection();
conn.setAutoCommit(false);
//取消数据的自动提交
String sql1 = "update t_user set balance = balance - 100 where username = ?";
String sql2 = "update t_user set balance = balance + 100 where username = ?";
update2(conn, sql1, "嬴政");
System.out.println(10 / 0);
update2(conn, sql2, "李世民");
System.out.println("转账成功!");
//提交数据
conn.commit();
} catch (Exception e) {
e.printStackTrace();
try {
conn.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
JDBC小结
- 两种思想
- 面向接口编程
- ORM(Object realtional mapping)
- 一个数据表对应一个java类
- 表中的一条记录对应java类的一个对象
- 表中的一个字段对应java类的一个属性
sql是需要结合列名和表的属性值来写,注意起别名
- 两种技术
- JDBC结果集的元数据:ResultSetMetaData
- 获取列数:getColumnCount()
- 获取列的别名:getColumnLabel()
- 通过反射,创建指定类的对象,获取指定的属性并赋值
- JDBC结果集的元数据:ResultSetMetaData
数据库连接池
Spring
概述
- IOC
- Aop
- JdbcTemplate
- 事务管理
- Spring5新特性
Spring有两个核心
- IOC:控制反转,
- Aop:面向切面
IOC
-
把对象创建和对象之间的调用过程交给Spring管理
-
使用IOC的目的是为了降低耦合度
-
IoC容器负责实例化,配置和组装对象。 IoC容器从XML文件获取信息并相应地工作。 IoC容器执行的主要任务是:
-
实例化应用程序类
-
配置对象
-
组装对象之间的依赖关系
-
有两种类型的IoC容器。它们是:
- BeanFactory
- ApplicationContext
IOC的底层原理
- xml解析
- 工厂模式
- 反射
实例的创建
传统方式
缺点是耦合度太高了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3Cl8Avvf-1663638076792)(/Users/huijia/Library/Application Support/typora-user-images/image-20220829154723234.png)]
工厂模式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t5HiI8gG-1663638076792)(/Users/huijia/Library/Application Support/typora-user-images/image-20220829155548244.png)]
IOC方式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QIX0GS3W-1663638076793)(/Users/huijia/Library/Application Support/typora-user-images/image-20220829160240191.png)]
IOC接口
- IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
- Spring提供IOC容器实现两种方式(两个接口)
- BeanFactory 是spring内部使用的接口,不提供开发人员使用
- ApplicationContext 是BeanFactory的子接口,提供更强大的功能,一般开发人员进行使用
BeanFactory和ApplicationContext之间的区别
org.springframework.beans.factory。 **BeanFactory** 和org.springframework.context。 **ApplicationContext** 接口充当IoC容器。 ApplicationContext接口建立在BeanFactory接口的顶部。它比BeanFactory增加了一些额外的功能,例如与Spring的AOP的简单集成,消息资源处理(用于I18N),事件传播,Web应用程序的特定于应用程序层的上下文(例如WebApplicationContext)。因此,使用ApplicationContext比使用BeanFactory更好。
使用BeanFactory
加载配置文件时不会创建对象,获取对象时才会创建对象
XmlBeanFactory是BeanFactory接口的实现类。要使用BeanFactory,我们需要创建XmlBeanFactory类的实例,如下所示:
示例
Resource resource=new ClassPathResource("applicationContext.xml");
BeanFactory factory=new XmlBeanFactory(resource);
XmlBeanFactory类的构造函数接收Resource对象,因此我们需要传递该资源对象来创建BeanFactory对象。
使用ApplicationContext
加载配置文件时就会把在配置文件对象进行创建
ClassPathXmlApplicationContext类是ApplicationContext接口的实现类。我们需要实例化ClassPathXmlApplicationContext类以使用ApplicationContext,如下所示:
示例
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
ClassPathXmlApplicationContext类的构造函数接收字符串,因此我们可以传递xml文件的名称来创建ApplicationContext的实例。
IOC操作Bean管理
- spring创建对象
- Spring注入属性
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P4FO2MzZ-1663638076793)(/Users/huijia/Library/Application Support/typora-user-images/image-20220829185155201.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9se2BfKZ-1663638076793)(/Users/huijia/Library/Application Support/typora-user-images/image-20220829193844785.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-59PqRtEa-1663638076793)(/Users/huijia/Library/Application Support/typora-user-images/image-20220829194041361.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0wyvgq5V-1663638076794)(/Users/huijia/Library/Application Support/typora-user-images/image-20220829194351985.png)]
有参构造配置
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iuEfV9Kq-1663638076794)(/Users/huijia/Library/Application Support/typora-user-images/image-20220829194708039.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MqpUy8zi-1663638076795)(/Users/huijia/Library/Application Support/typora-user-images/image-20220829195024389.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ig94VvEl-1663638076795)(/Users/huijia/Library/Application Support/typora-user-images/image-20220829195530604.png)]
注入其他属性
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PMH1zAn8-1663638076795)(/Users/huijia/Library/Application Support/typora-user-images/image-20220829200013749.png)]
注入外部类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rOWyyMY5-1663638076796)(/Users/huijia/Library/Application Support/typora-user-images/image-20220829201013349.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GLZAokzY-1663638076796)(/Users/huijia/Library/Application Support/typora-user-images/image-20220829200906230.png)]
内部bean和级连赋值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uSQyRs4q-1663638076796)(/Users/huijia/Library/Application Support/typora-user-images/image-20220829201920549.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VT62XlaD-1663638076797)(/Users/huijia/Library/Application Support/typora-user-images/image-20220829202342455.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r98wJaLr-1663638076797)(/Users/huijia/Library/Application Support/typora-user-images/image-20220829202642785.png)]
前提是ben要有get方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LuQEmZRC-1663638076797)(/Users/huijia/Library/Application Support/typora-user-images/image-20220829204225117.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d1QE53B8-1663638076798)(/Users/huijia/Library/Application Support/typora-user-images/image-20220829204659432.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XV1Bae7Y-1663638076798)(/Users/huijia/Library/Application Support/typora-user-images/image-20220829205117360.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gil0IHpQ-1663638076798)(/Users/huijia/Library/Application Support/typora-user-images/image-20220829205336687.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FGVPyrNf-1663638076798)(/Users/huijia/Library/Application Support/typora-user-images/image-20220830132252025.png)]
IOc SpringBean管理的作用域
在spring里面 设置创建bean实例是单实例还是多实例
默认是单实例
scope的属性值
- 默认值是singleton 表示单实例
- prototype。表示多实例
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-USjO3B55-1663638076799)(/Users/huijia/Library/Application Support/typora-user-images/image-20220830133153669.png)]
设置scope值是prototype时,不是在加载spring配置文件时候创建对象,在调用getBean方法时差u你更创建多实例对象
Bean管理的生命周期
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v1yv7JHj-1663638076799)(/Users/huijia/Library/Application Support/typora-user-images/image-20220830134917831.png)]。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e5E1Ppsf-1663638076799)(/Users/huijia/Library/Application Support/typora-user-images/image-20220830141604925.png)]
可以通过autowire 实现 自动装配
- byName。根据属性民称注入
- byType 根据属性类型注入
IOC操作Bean管理基于注解方式
spring针对Bean管理中茶u你更加爱你对象提供注解
- @Component
- @Service
- @Controller
- @Repository
如上的注解的功能是一样的,都可以用来创建Bean实例
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y9NQADcl-1663638076800)(/Users/huijia/Library/Application Support/typora-user-images/image-20220831132607295.png)]