SQLAlchemy是Python中最流行的ORM(对象关系映射)框架之一,它提供了高效且灵活的数据库操作方式。本文将介绍如何使用SQLAlchemy ORM进行数据库操作。

目录

安装SQLAlchemy

核心概念

连接数据库

定义数据模型

创建数据库表

基本CRUD操作

查询数据

关系操作

事务管理

最佳实践

安装

bash

pip install sqlalchemy

如果需要连接特定数据库,还需安装相应的驱动程序:

bash

# PostgreSQL

pip install psycopg2-binary

# MySQL

pip install mysql-connector-python

# SQLite (Python标准库已包含,无需额外安装)

核心概念

Engine:数据库连接的引擎,负责与数据库通信

Session:数据库会话,管理所有持久化操作

Model:数据模型类,对应数据库中的表

Query:查询对象,用于构建和执行数据库查询

连接数据库

python

from sqlalchemy import create_engine

from sqlalchemy.orm import sessionmaker

# 创建数据库连接引擎

# SQLite示例

engine = create_engine('sqlite:///example.db', echo=True)

# PostgreSQL示例

# engine = create_engine('postgresql://username:password@localhost:5432/mydatabase')

# MySQL示例

# engine = create_engine('mysql+mysqlconnector://username:password@localhost:3306/mydatabase')

# 创建会话工厂

SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

# 创建会话实例

session = SessionLocal()

定义数据模型

python

from sqlalchemy import Column, Integer, String, ForeignKey

from sqlalchemy.orm import relationship, declarative_base

# 创建基类

Base = declarative_base()

class User(Base):

__tablename__ = 'users'

id = Column(Integer, primary_key=True, index=True)

name = Column(String(50), nullable=False)

email = Column(String(100), unique=True, index=True)

# 定义一对多关系

posts = relationship("Post", back_populates="author")

class Post(Base):

__tablename__ = 'posts'

id = Column(Integer, primary_key=True, index=True)

title = Column(String(100), nullable=False)

content = Column(String(500))

author_id = Column(Integer, ForeignKey('users.id'))

# 定义多对一关系

author = relationship("User", back_populates="posts")

# 定义多对多关系(通过关联表)

tags = relationship("Tag", secondary="post_tags", back_populates="posts")

class Tag(Base):

__tablename__ = 'tags'

id = Column(Integer, primary_key=True, index=True)

name = Column(String(30), unique=True, nullable=False)

posts = relationship("Post", secondary="post_tags", back_populates="tags")

# 关联表(用于多对多关系)

class PostTag(Base):

__tablename__ = 'post_tags'

post_id = Column(Integer, ForeignKey('posts.id'), primary_key=True)

tag_id = Column(Integer, ForeignKey('tags.id'), primary_key=True)

创建数据库表

python

# 创建所有表

Base.metadata.create_all(bind=engine)

# 删除所有表

# Base.metadata.drop_all(bind=engine)

基本CRUD操作

创建数据

python

# 创建新用户

new_user = User(name="张三", email="zhangsan@example.com")

session.add(new_user)

session.commit()

# 批量创建

session.add_all([

User(name="李四", email="lisi@example.com"),

User(name="王五", email="wangwu@example.com")

])

session.commit()

读取数据

python

# 获取所有用户

users = session.query(User).all()

# 获取第一个用户

first_user = session.query(User).first()

# 根据ID获取用户

user = session.query(User).get(1)

更新数据

python

# 查询并更新

user = session.query(User).get(1)

user.name = "张三四"

session.commit()

# 批量更新

session.query(User).filter(User.name.like("张%")).update({"name": "张氏"}, synchronize_session=False)

session.commit()

删除数据

python

# 查询并删除

user = session.query(User).get(1)

session.delete(user)

session.commit()

# 批量删除

session.query(User).filter(User.name == "李四").delete(synchronize_session=False)

session.commit()

查询数据

基本查询

python

# 获取所有记录

users = session.query(User).all()

# 获取特定字段

names = session.query(User.name).all()

# 排序

users = session.query(User).order_by(User.name.desc()).all()

# 限制结果数量

users = session.query(User).limit(10).all()

# 偏移量

users = session.query(User).offset(5).limit(10).all()

过滤查询

python

from sqlalchemy import or_

# 等值过滤

user = session.query(User).filter(User.name == "张三").first()

# 模糊查询

users = session.query(User).filter(User.name.like("张%")).all()

# IN查询

users = session.query(User).filter(User.name.in_(["张三", "李四"])).all()

# 多条件查询

users = session.query(User).filter(

User.name == "张三",

User.email.like("%@example.com")

).all()

# 或条件

users = session.query(User).filter(

or_(User.name == "张三", User.name == "李四")

).all()

# 不等于

users = session.query(User).filter(User.name != "张三").all()

聚合查询

python

from sqlalchemy import func

# 计数

count = session.query(User).count()

# 分组计数

user_post_count = session.query(

User.name,

func.count(Post.id)

).join(Post).group_by(User.name).all()

# 求和、平均值等

avg_id = session.query(func.avg(User.id)).scalar()

连接查询

python

# 内连接

results = session.query(User, Post).join(Post).filter(Post.title.like("%Python%")).all()

# 左外连接

results = session.query(User, Post).outerjoin(Post).all()

# 指定连接条件

results = session.query(User, Post).join(Post, User.id == Post.author_id).all()

关系操作

python

# 创建带关系的对象

user = User(name="赵六", email="zhaoliu@example.com")

post = Post(title="我的第一篇博客", content="Hello World!", author=user)

session.add(post)

session.commit()

# 通过关系访问

print(f"文章 '{post.title}' 的作者是 {post.author.name}")

print(f"用户 {user.name} 的所有文章:")

for p in user.posts:

print(f" - {p.title}")

# 多对多关系操作

python_tag = Tag(name="Python")

sqlalchemy_tag = Tag(name="SQLAlchemy")

post.tags.append(python_tag)

post.tags.append(sqlalchemy_tag)

session.commit()

print(f"文章 '{post.title}' 的标签:")

for tag in post.tags:

print(f" - {tag.name}")

事务管理

python

# 自动提交事务

try:

user = User(name="测试用户", email="test@example.com")

session.add(user)

session.commit()

except Exception as e:

session.rollback()

print(f"发生错误: {e}")

# 使用事务上下文管理器

from sqlalchemy.orm import Session

def create_user(session: Session, name: str, email: str):

try:

user = User(name=name, email=email)

session.add(user)

session.commit()

return user

except:

session.rollback()

raise

# 嵌套事务

with session.begin_nested():

user = User(name="事务用户", email="transaction@example.com")

session.add(user)

# 保存点

savepoint = session.begin_nested()

try:

user = User(name="保存点用户", email="savepoint@example.com")

session.add(user)

savepoint.commit()

except:

savepoint.rollback()

最佳实践

会话管理:为每个请求创建新会话,请求结束后关闭

异常处理:始终处理异常并适当回滚事务

延迟加载:注意N+1查询问题,使用 eager loading 优化

连接池:合理配置连接池大小和超时设置

数据验证:在模型层或应用层验证数据完整性

python

# 使用上下文管理器管理会话

from contextlib import contextmanager

@contextmanager

def get_db():

db = SessionLocal()

try:

yield db

db.commit()

except Exception:

db.rollback()

raise

finally:

db.close()

# 使用示例

with get_db() as db:

user = User(name="上下文用户", email="context@example.com")

db.add(user)

总结

SQLAlchemy ORM提供了强大而灵活的数据库操作方式,通过本文的介绍,您应该能够:

安装和配置SQLAlchemy

定义数据模型和关系

执行基本的CRUD操作

构建复杂查询

管理数据库事务

遵循最佳实践

SQLAlchemy还有更多高级特性,如混合属性、事件监*、自定义查询等,值得进一步探索学习。

这是一个非常经典的Spring面试题,也是理解Spring核心思想的关键。很多人会把它们混为一谈,但实际上它们描述的是同一个概念的两个不同侧面。

让我用一个非常通俗易懂的方式来解释。

核心结论

  • 控制反转(IoC)是一种设计原则或思想。

  • 依赖注入(DI)是实现控制反转这种思想的一种具体技术模式。

可以把它们的关系理解为:

“战略” vs “战术”

  • IoC是战略目标:我们要将程序的控制权反转过来。

  • DI是战术手段:我们通过“注入”依赖的方式来实现这个目标。


1. 控制反转(Inversion of Control - IoC)

核心思想: 将对象的创建、组装、生命周期的控制权,从应用程序代码中“反转”给一个外部容器(在Spring中就是IoC容器)。

传统开发模式(正转):

  • 你需要一个对象(比如Car),你会在代码里直接new Car()

  • 你的代码主动去创建和管理它所依赖的对象。

  • 控制权在程序本身。

java

// 传统方式:程序员自己控制

public class Car {

private Engine engine;

public Car() {

// 程序员主动创建依赖

this.engine = new Engine(); // 控制权在Car类内部

}bbs.n22t5x4.cn/PosT/1110_.hTM
bbs.yitaomoney.com/PosT/1110_.hTM
bbs.beijingyifu.com/PosT/1110_.hTM
bbs.c4mfpep.cn/PosT/1110_.hTM
bbs.ilqlqq5.cn/PosT/1110_.hTM
bbs.hnr2k1h.cn/PosT/1110_.hTM
bbs.42518ic.cn/PosT/1110_.hTM
bbs.rhsf8uz.cn/PosT/1110_.hTM
bbs.lydlnp6.cn/PosT/1110_.hTM
bbs.2v5hp0t.cn/PosT/1110_.hTM
bbs.rpvesuv.cn/PosT/1110_.hTM
bbs.pqojf3j.cn/PosT/1110_.hTM
bbs.o28m7pw.cn/PosT/1110_.hTM
m.emgtoa.info/PosT/1110_.hTM
m.jcmqkl.info/PosT/1110_.hTM
m.vharzd.info/PosT/1110_.hTM
m.gupeqo.info/PosT/1110_.hTM
m.pwgknr.info/PosT/1110_.hTM
m.wvytua.info/PosT/1110_.hTM
m.wnuanx.info/PosT/1110_.hTM
m.aufpkg.info/PosT/1110_.hTM
m.apqcil.info/PosT/1110_.hTM
m.vwlucq.info/PosT/1110_.hTM
m.uglerk.info/PosT/1110_.hTM
m.ndkubr.info/PosT/1110_.hTM
m.egpxqn.info/PosT/1110_.hTM
m.bwjskx.info/PosT/1110_.hTM
m.xcbypr.info/PosT/1110_.hTM
m.hvsxlk.info/PosT/1110_.hTM
m.jfhedc.info/PosT/1110_.hTM
m.szjtlb.info/PosT/1110_.hTM
m.ofzuvm.info/PosT/1110_.hTM
m.roljdm.info/PosT/1110_.hTM
m.x4qdbmz.cn/PosT/1110_.hTM
m.lq20irz.cn/PosT/1110_.hTM
m.irkh4dm.cn/PosT/1110_.hTM
m.izryqi1.cn/PosT/1110_.hTM
m.6j1n5i6.cn/PosT/1110_.hTM
m.j4b77ta.cn/PosT/1110_.hTM
m.vkvwy7f.cn/PosT/1110_.hTM
m.xl9st9o.cn/PosT/1110_.hTM
m.d8fllfw.cn/PosT/1110_.hTM
m.b9g9ogh.cn/PosT/1110_.hTM
m.4e6vl6d.cn/PosT/1110_.hTM
m.mqof912.cn/PosT/1110_.hTM
m.ex0qf0u.cn/PosT/1110_.hTM
m.kmgfdil.cn/PosT/1110_.hTM
m.fepx0c3.cn/PosT/1110_.hTM
m.xc26fn2.cn/PosT/1110_.hTM
m.goytj4w.cn/PosT/1110_.hTM
m.kv9e40n.cn/PosT/1110_.hTM
m.2jyisza.cn/PosT/1110_.hTM
m.zh91vkm.cn/PosT/1110_.hTM
m.w8352el.cn/PosT/1110_.hTM
m.6sa6cdr.cn/PosT/1110_.hTM
m.tegjhld.cn/PosT/1110_.hTM
m.o2tnu1o.cn/PosT/1110_.hTM
m.731j99k.cn/PosT/1110_.hTM
m.od0f0wx.cn/PosT/1110_.hTM
m.tiziv58.cn/PosT/1110_.hTM
m.v2bs2y9.cn/PosT/1110_.hTM
m.lmwc5ua.cn/PosT/1110_.hTM
m.n22t5x4.cn/PosT/1110_.hTM
m.yitaomoney.com/PosT/1110_.hTM
m.beijingyifu.com/PosT/1110_.hTM
m.c4mfpep.cn/PosT/1110_.hTM
m.ilqlqq5.cn/PosT/1110_.hTM
m.hnr2k1h.cn/PosT/1110_.hTM
m.42518ic.cn/PosT/1110_.hTM
m.rhsf8uz.cn/PosT/1110_.hTM
m.lydlnp6.cn/PosT/1110_.hTM
m.2v5hp0t.cn/PosT/1110_.hTM
m.rpvesuv.cn/PosT/1110_.hTM
m.pqojf3j.cn/PosT/1110_.hTM
m.o28m7pw.cn/PosT/1110_.hTM
5g.emgtoa.info/PosT/1110_.hTM
5g.jcmqkl.info/PosT/1110_.hTM
5g.vharzd.info/PosT/1110_.hTM
5g.gupeqo.info/PosT/1110_.hTM
5g.pwgknr.info/PosT/1110_.hTM
5g.wvytua.info/PosT/1110_.hTM
5g.wnuanx.info/PosT/1110_.hTM
5g.aufpkg.info/PosT/1110_.hTM
5g.apqcil.info/PosT/1110_.hTM
5g.vwlucq.info/PosT/1110_.hTM
5g.uglerk.info/PosT/1110_.hTM
5g.ndkubr.info/PosT/1110_.hTM
5g.egpxqn.info/PosT/1110_.hTM
5g.bwjskx.info/PosT/1110_.hTM
5g.xcbypr.info/PosT/1110_.hTM
5g.hvsxlk.info/PosT/1110_.hTM
5g.jfhedc.info/PosT/1110_.hTM
5g.szjtlb.info/PosT/1110_.hTM
5g.ofzuvm.info/PosT/1110_.hTM
5g.roljdm.info/PosT/1110_.hTM
5g.x4qdbmz.cn/PosT/1110_.hTM
5g.lq20irz.cn/PosT/1110_.hTM
5g.irkh4dm.cn/PosT/1110_.hTM
5g.izryqi1.cn/PosT/1110_.hTM
5g.6j1n5i6.cn/PosT/1110_.hTM

}

控制反转模式(反转):

  • 你不再自己new对象,而是由一个“容器”来帮你创建好、组装好,然后“送”给你。

  • 你的代码是被动接收它所需要的依赖。

  • 控制权转移到了外部容器。

java

// IoC方式:容器控制

public class Car {

private Engine engine;

// 容器会负责把创建好的Engine对象“注入”到这里

public Car(Engine engine) { // 控制权在容器

this.engine = engine;

}5g.j4b77ta.cn/PosT/1110_.hTM
5g.vkvwy7f.cn/PosT/1110_.hTM
5g.xl9st9o.cn/PosT/1110_.hTM
5g.d8fllfw.cn/PosT/1110_.hTM
5g.b9g9ogh.cn/PosT/1110_.hTM
5g.4e6vl6d.cn/PosT/1110_.hTM
5g.mqof912.cn/PosT/1110_.hTM
5g.ex0qf0u.cn/PosT/1110_.hTM
5g.kmgfdil.cn/PosT/1110_.hTM
5g.fepx0c3.cn/PosT/1110_.hTM
5g.xc26fn2.cn/PosT/1110_.hTM
5g.goytj4w.cn/PosT/1110_.hTM
5g.kv9e40n.cn/PosT/1110_.hTM
5g.2jyisza.cn/PosT/1110_.hTM
5g.zh91vkm.cn/PosT/1110_.hTM
5g.w8352el.cn/PosT/1110_.hTM
5g.6sa6cdr.cn/PosT/1110_.hTM
5g.tegjhld.cn/PosT/1110_.hTM
5g.o2tnu1o.cn/PosT/1110_.hTM
5g.731j99k.cn/PosT/1110_.hTM
5g.od0f0wx.cn/PosT/1110_.hTM
5g.tiziv58.cn/PosT/1110_.hTM
5g.v2bs2y9.cn/PosT/1110_.hTM
5g.lmwc5ua.cn/PosT/1110_.hTM
5g.n22t5x4.cn/PosT/1110_.hTM
5g.yitaomoney.com/PosT/1110_.hTM
5g.beijingyifu.com/PosT/1110_.hTM
5g.c4mfpep.cn/PosT/1110_.hTM
5g.ilqlqq5.cn/PosT/1110_.hTM
5g.hnr2k1h.cn/PosT/1110_.hTM
5g.42518ic.cn/PosT/1110_.hTM
5g.rhsf8uz.cn/PosT/1110_.hTM
5g.lydlnp6.cn/PosT/1110_.hTM
5g.2v5hp0t.cn/PosT/1110_.hTM
5g.rpvesuv.cn/PosT/1110_.hTM
5g.pqojf3j.cn/PosT/1110_.hTM
5g.o28m7pw.cn/PosT/1110_.hTM
map.emgtoa.info/PosT/1110_.hTM
map.jcmqkl.info/PosT/1110_.hTM
map.vharzd.info/PosT/1110_.hTM
map.gupeqo.info/PosT/1110_.hTM
map.pwgknr.info/PosT/1110_.hTM
map.wvytua.info/PosT/1110_.hTM
map.wnuanx.info/PosT/1110_.hTM
map.aufpkg.info/PosT/1110_.hTM
map.apqcil.info/PosT/1110_.hTM
map.vwlucq.info/PosT/1110_.hTM
map.uglerk.info/PosT/1110_.hTM
map.ndkubr.info/PosT/1110_.hTM
map.egpxqn.info/PosT/1110_.hTM
map.bwjskx.info/PosT/1110_.hTM
map.xcbypr.info/PosT/1110_.hTM
map.hvsxlk.info/PosT/1110_.hTM
map.jfhedc.info/PosT/1110_.hTM
map.szjtlb.info/PosT/1110_.hTM
map.ofzuvm.info/PosT/1110_.hTM
map.roljdm.info/PosT/1110_.hTM
map.x4qdbmz.cn/PosT/1110_.hTM
map.lq20irz.cn/PosT/1110_.hTM
map.irkh4dm.cn/PosT/1110_.hTM
map.izryqi1.cn/PosT/1110_.hTM
map.6j1n5i6.cn/PosT/1110_.hTM
map.j4b77ta.cn/PosT/1110_.hTM
map.vkvwy7f.cn/PosT/1110_.hTM
map.xl9st9o.cn/PosT/1110_.hTM
map.d8fllfw.cn/PosT/1110_.hTM
map.b9g9ogh.cn/PosT/1110_.hTM
map.4e6vl6d.cn/PosT/1110_.hTM
map.mqof912.cn/PosT/1110_.hTM
map.ex0qf0u.cn/PosT/1110_.hTM
map.kmgfdil.cn/PosT/1110_.hTM
map.fepx0c3.cn/PosT/1110_.hTM
map.xc26fn2.cn/PosT/1110_.hTM
map.goytj4w.cn/PosT/1110_.hTM
map.kv9e40n.cn/PosT/1110_.hTM
map.2jyisza.cn/PosT/1110_.hTM
map.zh91vkm.cn/PosT/1110_.hTM
map.w8352el.cn/PosT/1110_.hTM
map.6sa6cdr.cn/PosT/1110_.hTM
map.tegjhld.cn/PosT/1110_.hTM
map.o2tnu1o.cn/PosT/1110_.hTM
map.731j99k.cn/PosT/1110_.hTM
map.od0f0wx.cn/PosT/1110_.hTM
map.tiziv58.cn/PosT/1110_.hTM
map.v2bs2y9.cn/PosT/1110_.hTM
map.lmwc5ua.cn/PosT/1110_.hTM
map.n22t5x4.cn/PosT/1110_.hTM
map.yitaomoney.com/PosT/1110_.hTM
map.beijingyifu.com/PosT/1110_.hTM
map.c4mfpep.cn/PosT/1110_.hTM
map.ilqlqq5.cn/PosT/1110_.hTM
map.hnr2k1h.cn/PosT/1110_.hTM
map.42518ic.cn/PosT/1110_.hTM
map.rhsf8uz.cn/PosT/1110_.hTM
map.lydlnp6.cn/PosT/1110_.hTM
map.2v5hp0t.cn/PosT/1110_.hTM
map.rpvesuv.cn/PosT/1110_.hTM
map.pqojf3j.cn/PosT/1110_.hTM
map.o28m7pw.cn/PosT/1110_.hTM
wap.emgtoa.info/PosT/1110_.hTM
wap.jcmqkl.info/PosT/1110_.hTM
wap.vharzd.info/PosT/1110_.hTM
wap.gupeqo.info/PosT/1110_.hTM
wap.pwgknr.info/PosT/1110_.hTM
wap.wvytua.info/PosT/1110_.hTM
wap.wnuanx.info/PosT/1110_.hTM
wap.aufpkg.info/PosT/1110_.hTM
wap.apqcil.info/PosT/1110_.hTM
wap.vwlucq.info/PosT/1110_.hTM
wap.uglerk.info/PosT/1110_.hTM
wap.ndkubr.info/PosT/1110_.hTM
wap.egpxqn.info/PosT/1110_.hTM
wap.bwjskx.info/PosT/1110_.hTM
wap.xcbypr.info/PosT/1110_.hTM
wap.hvsxlk.info/PosT/1110_.hTM
wap.jfhedc.info/PosT/1110_.hTM
wap.szjtlb.info/PosT/1110_.hTM
wap.ofzuvm.info/PosT/1110_.hTM
wap.roljdm.info/PosT/1110_.hTM
wap.x4qdbmz.cn/PosT/1110_.hTM
wap.lq20irz.cn/PosT/1110_.hTM
wap.irkh4dm.cn/PosT/1110_.hTM
wap.izryqi1.cn/PosT/1110_.hTM
wap.6j1n5i6.cn/PosT/1110_.hTM
wap.j4b77ta.cn/PosT/1110_.hTM
wap.vkvwy7f.cn/PosT/1110_.hTM
wap.xl9st9o.cn/PosT/1110_.hTM
wap.d8fllfw.cn/PosT/1110_.hTM
wap.b9g9ogh.cn/PosT/1110_.hTM
wap.4e6vl6d.cn/PosT/1110_.hTM
wap.mqof912.cn/PosT/1110_.hTM
wap.ex0qf0u.cn/PosT/1110_.hTM
wap.kmgfdil.cn/PosT/1110_.hTM
wap.fepx0c3.cn/PosT/1110_.hTM
wap.xc26fn2.cn/PosT/1110_.hTM
wap.goytj4w.cn/PosT/1110_.hTM
wap.kv9e40n.cn/PosT/1110_.hTM
wap.2jyisza.cn/PosT/1110_.hTM
wap.zh91vkm.cn/PosT/1110_.hTM
wap.w8352el.cn/PosT/1110_.hTM
wap.6sa6cdr.cn/PosT/1110_.hTM
wap.tegjhld.cn/PosT/1110_.hTM
wap.o2tnu1o.cn/PosT/1110_.hTM
wap.731j99k.cn/PosT/1110_.hTM
wap.od0f0wx.cn/PosT/1110_.hTM
wap.tiziv58.cn/PosT/1110_.hTM
wap.v2bs2y9.cn/PosT/1110_.hTM
wap.lmwc5ua.cn/PosT/1110_.hTM
wap.n22t5x4.cn/PosT/1110_.hTM
wap.yitaomoney.com/PosT/1110_.hTM
wap.beijingyifu.com/PosT/1110_.hTM
wap.c4mfpep.cn/PosT/1110_.hTM
wap.ilqlqq5.cn/PosT/1110_.hTM
wap.hnr2k1h.cn/PosT/1110_.hTM
wap.42518ic.cn/PosT/1110_.hTM
wap.rhsf8uz.cn/PosT/1110_.hTM
wap.lydlnp6.cn/PosT/1110_.hTM
wap.2v5hp0t.cn/PosT/1110_.hTM
wap.rpvesuv.cn/PosT/1110_.hTM
wap.pqojf3j.cn/PosT/1110_.hTM
wap.o28m7pw.cn/PosT/1110_.hTM
book.emgtoa.info/PosT/1110_.hTM
book.jcmqkl.info/PosT/1110_.hTM
book.vharzd.info/PosT/1110_.hTM
book.gupeqo.info/PosT/1110_.hTM
book.pwgknr.info/PosT/1110_.hTM
book.wvytua.info/PosT/1110_.hTM
book.wnuanx.info/PosT/1110_.hTM
book.aufpkg.info/PosT/1110_.hTM
book.apqcil.info/PosT/1110_.hTM
book.vwlucq.info/PosT/1110_.hTM
book.uglerk.info/PosT/1110_.hTM
book.ndkubr.info/PosT/1110_.hTM
book.egpxqn.info/PosT/1110_.hTM
book.bwjskx.info/PosT/1110_.hTM
book.xcbypr.info/PosT/1110_.hTM
book.hvsxlk.info/PosT/1110_.hTM
book.jfhedc.info/PosT/1110_.hTM
book.szjtlb.info/PosT/1110_.hTM
book.ofzuvm.info/PosT/1110_.hTM
book.roljdm.info/PosT/1110_.hTM
book.x4qdbmz.cn/PosT/1110_.hTM
book.lq20irz.cn/PosT/1110_.hTM
book.irkh4dm.cn/PosT/1110_.hTM
book.izryqi1.cn/PosT/1110_.hTM
book.6j1n5i6.cn/PosT/1110_.hTM
book.j4b77ta.cn/PosT/1110_.hTM
book.vkvwy7f.cn/PosT/1110_.hTM
book.xl9st9o.cn/PosT/1110_.hTM
book.d8fllfw.cn/PosT/1110_.hTM
book.b9g9ogh.cn/PosT/1110_.hTM
book.4e6vl6d.cn/PosT/1110_.hTM
book.mqof912.cn/PosT/1110_.hTM
book.ex0qf0u.cn/PosT/1110_.hTM
book.kmgfdil.cn/PosT/1110_.hTM
book.fepx0c3.cn/PosT/1110_.hTM
book.xc26fn2.cn/PosT/1110_.hTM
book.goytj4w.cn/PosT/1110_.hTM
book.kv9e40n.cn/PosT/1110_.hTM
book.2jyisza.cn/PosT/1110_.hTM

}

IoC容器的职责:

  • 创建对象

  • 弄清楚对象之间的依赖关系(比如Car依赖Engine

  • 将依赖的对象装配到一起

  • 管理对象的生命周期(何时创建,何时销毁)


2. 依赖注入(Dependency Injection - DI)

核心思想: 是实现IoC的具体技术。它描述的是“如何”将依赖关系传递给一个组件。具体来说,就是容器通过构造函数、Setter方法或接口等方式,将依赖对象“注入”到需要它的组件中。

依赖注入主要有三种方式:

1. 构造器注入(推荐)

容器通过调用类的构造函数来注入依赖。

java

@Component

public class Car {

private final Engine engine;

// 容器会在这里注入一个Engine实例

@Autowired // Spring 4.3后,如果只有一个构造器,可省略此注解

public Car(Engine engine) {

this.engine = engine;

}book.zh91vkm.cn/PosT/1110_.hTM
book.w8352el.cn/PosT/1110_.hTM
book.6sa6cdr.cn/PosT/1110_.hTM
book.tegjhld.cn/PosT/1110_.hTM
book.o2tnu1o.cn/PosT/1110_.hTM
book.731j99k.cn/PosT/1110_.hTM
book.od0f0wx.cn/PosT/1110_.hTM
book.tiziv58.cn/PosT/1110_.hTM
book.v2bs2y9.cn/PosT/1110_.hTM
book.lmwc5ua.cn/PosT/1110_.hTM
book.n22t5x4.cn/PosT/1110_.hTM
book.yitaomoney.com/PosT/1110_.hTM
book.beijingyifu.com/PosT/1110_.hTM
book.c4mfpep.cn/PosT/1110_.hTM
book.ilqlqq5.cn/PosT/1110_.hTM
book.hnr2k1h.cn/PosT/1110_.hTM
book.42518ic.cn/PosT/1110_.hTM
book.rhsf8uz.cn/PosT/1110_.hTM
book.lydlnp6.cn/PosT/1110_.hTM
book.2v5hp0t.cn/PosT/1110_.hTM
book.rpvesuv.cn/PosT/1110_.hTM
book.pqojf3j.cn/PosT/1110_.hTM
book.o28m7pw.cn/PosT/1110_.hTM
bbs.emgtoa.info/PosT/1110_.hTM
bbs.jcmqkl.info/PosT/1110_.hTM
bbs.vharzd.info/PosT/1110_.hTM
bbs.gupeqo.info/PosT/1110_.hTM
bbs.pwgknr.info/PosT/1110_.hTM
bbs.wvytua.info/PosT/1110_.hTM
bbs.wnuanx.info/PosT/1110_.hTM
bbs.aufpkg.info/PosT/1110_.hTM
bbs.apqcil.info/PosT/1110_.hTM
bbs.vwlucq.info/PosT/1110_.hTM
bbs.uglerk.info/PosT/1110_.hTM
bbs.ndkubr.info/PosT/1110_.hTM
bbs.egpxqn.info/PosT/1110_.hTM
bbs.bwjskx.info/PosT/1110_.hTM
bbs.xcbypr.info/PosT/1110_.hTM
bbs.hvsxlk.info/PosT/1110_.hTM
bbs.jfhedc.info/PosT/1110_.hTM
bbs.szjtlb.info/PosT/1110_.hTM
bbs.ofzuvm.info/PosT/1110_.hTM
bbs.roljdm.info/PosT/1110_.hTM
bbs.x4qdbmz.cn/PosT/1110_.hTM
bbs.lq20irz.cn/PosT/1110_.hTM
bbs.irkh4dm.cn/PosT/1110_.hTM
bbs.izryqi1.cn/PosT/1110_.hTM
bbs.6j1n5i6.cn/PosT/1110_.hTM
bbs.j4b77ta.cn/PosT/1110_.hTM
bbs.vkvwy7f.cn/PosT/1110_.hTM
bbs.xl9st9o.cn/PosT/1110_.hTM
bbs.d8fllfw.cn/PosT/1110_.hTM
bbs.b9g9ogh.cn/PosT/1110_.hTM
bbs.4e6vl6d.cn/PosT/1110_.hTM
bbs.mqof912.cn/PosT/1110_.hTM
bbs.ex0qf0u.cn/PosT/1110_.hTM
bbs.kmgfdil.cn/PosT/1110_.hTM
bbs.fepx0c3.cn/PosT/1110_.hTM
bbs.xc26fn2.cn/PosT/1110_.hTM
bbs.goytj4w.cn/PosT/1110_.hTM
bbs.kv9e40n.cn/PosT/1110_.hTM
bbs.2jyisza.cn/PosT/1110_.hTM
bbs.zh91vkm.cn/PosT/1110_.hTM
bbs.w8352el.cn/PosT/1110_.hTM
bbs.6sa6cdr.cn/PosT/1110_.hTM
bbs.tegjhld.cn/PosT/1110_.hTM
bbs.o2tnu1o.cn/PosT/1110_.hTM
bbs.731j99k.cn/PosT/1110_.hTM
bbs.od0f0wx.cn/PosT/1110_.hTM
bbs.tiziv58.cn/PosT/1110_.hTM
bbs.v2bs2y9.cn/PosT/1110_.hTM
bbs.lmwc5ua.cn/PosT/1110_.hTM
bbs.n22t5x4.cn/PosT/1110_.hTM
bbs.yitaomoney.com/PosT/1110_.hTM
bbs.beijingyifu.com/PosT/1110_.hTM
bbs.c4mfpep.cn/PosT/1110_.hTM
bbs.ilqlqq5.cn/PosT/1110_.hTM
bbs.hnr2k1h.cn/PosT/1110_.hTM
bbs.42518ic.cn/PosT/1110_.hTM
bbs.rhsf8uz.cn/PosT/1110_.hTM
bbs.lydlnp6.cn/PosT/1110_.hTM
bbs.2v5hp0t.cn/PosT/1110_.hTM
bbs.rpvesuv.cn/PosT/1110_.hTM
bbs.pqojf3j.cn/PosT/1110_.hTM
bbs.o28m7pw.cn/PosT/1110_.hTM
m.emgtoa.info/PosT/1110_.hTM
m.jcmqkl.info/PosT/1110_.hTM
m.vharzd.info/PosT/1110_.hTM
m.gupeqo.info/PosT/1110_.hTM
m.pwgknr.info/PosT/1110_.hTM
m.wvytua.info/PosT/1110_.hTM
m.wnuanx.info/PosT/1110_.hTM
m.aufpkg.info/PosT/1110_.hTM
m.apqcil.info/PosT/1110_.hTM
m.vwlucq.info/PosT/1110_.hTM
m.uglerk.info/PosT/1110_.hTM
m.ndkubr.info/PosT/1110_.hTM
m.egpxqn.info/PosT/1110_.hTM
m.bwjskx.info/PosT/1110_.hTM
m.xcbypr.info/PosT/1110_.hTM

}

2. Setter方法注入

容器通过调用类的Setter方法来注入依赖。

java

@Component

public class Car {

private Engine engine;

// 容器会调用这个setter方法来注入Engine

@Autowired

public void setEngine(Engine engine) {

this.engine = engine;

}

}

3. 字段注入(现在不推荐)

容器通过反射直接给字段赋值。

java

@Component

public class Car {

@Autowired // 直接注入到字段

private Engine engine;

}


用一个生活中的比喻来总结

假设你想喝一杯咖啡

传统模式(正转):

  1. 你自己去种咖啡豆。

  2. 你自己去烘焙、研磨。

  3. 你自己用咖啡机冲泡。

  4. 你喝到咖啡。

    -> 你控制了所有环节,非常繁琐,高度耦合。

控制反转模式(IoC):

  • 你走进一家咖啡馆(IoC容器)

  • 你直接向服务员点单:“我要一杯拿铁”。

  • 服务员(容器)去后厨(创建并组装对象)让咖啡师(Bean)用咖啡机(另一个Bean)和牛奶(另一个Bean)做好一杯拿铁。

  • 服务员把这杯做好的拿铁(组装好的对象)递给你。

    -> 你不再关心制作过程,只关心最终结果。控制权反转给了咖啡馆。

依赖注入(DI)在这个比喻中:

  • 就是服务员把做好的拿铁“递给你”的这个“递”的动作

  • 它是实现“咖啡馆为你服务”这个“控制反转”思想的具体方式。


总结对比表

特性 控制反转(IoC) 依赖注入(DI)
本质 设计原则、思想 设计模式、具体技术
关系 目标 实现手段
关注点 控制权的转移(从程序转移到容器) 对象依赖关系的满足方式(通过注入)
范围 一个更广泛的概念,DI是它的子集 是实现IoC的特定方式,还有其他方式如服务定位器
类比 去咖啡馆喝咖啡的理念 服务员把咖啡递给你的这个具体动作

在Spring框架中,我们通过使用依赖注入这种最主流的方式,来实现控制反转这个崇高的设计目标,最终达到代码解耦、更易测试、更灵活的目的。所以当我们在谈论Spring的IoC时,通常指的就是它的依赖注入功能。

 

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐