Pygame库200行代码实现简易飞机大战

写在开头,因为这个小游戏的实验主要是帮助我熟悉pygame库的使用,所以游戏的一些地方可能存在不完善处,还望包涵。

安装使用库

pygame简介

pygame是跨平台python模块,专为电子游戏设计,包括图像、声音。建立在SDL基础上,允许实时电子游戏研发而无需被低级语言束缚, 开发者可以把精力放在游戏的架构上。

pgame中主要模块介绍

(1) pygame

pygame模块会自动导入其它的pygame相关模块。

pygame模块包括surface函数, 可以返回一个新的surface 对象。 init()函数是pygame游戏的核心,必须在进入游戏的主循环之前调用。init()会自动初始化其它所有模块。

(2) pygame.locals

包括在你自己的模块作用域内使用的名字(变量)。包括事件类型、键和视频模式等的名字。

(3) pygame.display

包括处理pygame显示方式的函数。包括普通窗口和全屏模式。 pygame.display中一些常用的方法如下:

  • flip:更新显示。
  • update:更新一部分时候使用update。
  • set_mode:设定显示的类型和尺寸。
  • set_caption:设定pygame程序的标题。
  • get_surface:调用flip和blit前返回一个可用于画图的surface对象。

(4) pygame.font

包括font函数,用于表现不同的字体。

(5) pygame.sprite

游戏精灵,Group用做sprite对象的容器。调用group对象的update对象,会自动调用所有sprite对象的update方法。

(6) pygame.mouse

隐藏鼠标光标,获取鼠标位置。

(7) pygame.event

追踪鼠标单击、按键按下和释放等事件。

(8) pygame.image

用于处理保存在GIF、PNG或者JPEG文件内的图像。

注:程序中除了local模块和font模块没有使用,其他模块均有涉及。

pygame的安装

你可以选择使用pycharm中工具栏下方的python packages搜索pygame进行安装,当然也可以使用cmd命令符中常用的pip install pygame 的方法。

安装超时网速慢,直接超时,可以指定国内源镜像。

pip install -i 国内镜像地址 包名

例如: pip install -i https://mirrors.aliyun.com/pypi/simple/ numpy

国内常用源镜像地址:

清华:https://pypi.tuna.tsinghua.edu.cn/simple
阿里云:http://mirrors.aliyun.com/pypi/simple/
中国科技大学:  https://pypi.mirrors.ustc.edu.cn/simple/
豆瓣:http://pypi.douban.com/simple/

验证安装

验证pygame是否安装成功,在cmd命令符中使用 pip list 语句,如果安装成功,我们可以在下方结果中找到。

程序原理

首先创建游戏的主窗体,主窗体的大小就是你背景图片的大小。

import pygame
#游戏初始化
pygame.init()
#创建游戏主窗口
screen = pygame.display.set_mode((480,700))
#绘制背景图香
#1 加载图像数据
background = pygame.image.load('./image/background.png')
#2 blit绘制图像
#从左上角绘制
screen.blit(background,(0,0))
pygame.display.update()
#卸载所有的模块
pygame.quit()

绘制图像时的方向,后面我们主机、敌机、背景、子弹的方向都需要注意这一点。

背景图像绘制完之后就是我们主机、敌机的绘制,我们可以在所有的绘制工作完成后再统一调用update方法

#绘制飞机图片
hero = pygame.image.load('./image/hero2.png')
screen.blit(hero,(150,300))
pygame.display.update()

其实飞机大战的原理和动画片的原理一致,我们需要对一个个按下的指令进行反应,从而形成一个连贯的画面,这里我们就需要使用到pygame库中的time模块

#创造时钟对象  屏幕绘制速率
clock = pygame.time.Clock()
#游戏循环
while True:
	#指定循环体内部代码的执行频率   每秒重复60次
	clock.tick(60)
	#将移动前飞机进行遮挡 达到动画效果
	screen.blit(background, (0, 0))
	screen.blit(hero,hero_rect)

如果你想停止程序,发现点击窗体右上角的关闭并无反应,因为你还未在循环体内进行事件监听,然后对时间进行判断

event_list = pygame.event.get()
for event in event_list:
	#判断是否为退出事件
	if event.type == pygame.QUIT:
		print("退出游戏...")
		#卸载所有模块
		pygame.quit()
		exit()

关于敌机的生成我们需要使用到sprite精灵和精灵组模块,创建两个一样的敌机,但是敌机的飞行速度不一样,然后将敌机精灵添加至敌机精灵组中,然后在循环体中我们不断将敌机精灵组进行绘制即可

enemy = GameSprite("./image/enemy0.png")
enemy1 = GameSprite("./image/enemy0.png",2)
enemy_group = pygame.sprite.Group(enemy,enemy1)

#精灵组调用方法
enemy_group.update()
enemy_group.draw(screen)

对上述部分代码进行整理简化,最后我们可以得到这样的效果图,主机和敌机都可以移动

import pygame
from plane_sprites import *

#游戏初始化
pygame.init()
#创建游戏主窗口
screen = pygame.display.set_mode((480,700))

#绘制背景图香
#1 加载图像数据
background = pygame.image.load('./image/background.png')
#2 blit绘制图像
#从左上角绘制
screen.blit(background,(0,0))
#3 update更新屏幕显示
# pygame.display.update()

#绘制飞机图片
hero = pygame.image.load('./image/hero2.png')
screen.blit(hero,(150,300))

#可以在所有绘制工作完成后,统一调用update方法
pygame.display.update()

#创造时钟对象  屏幕绘制速率
clock = pygame.time.Clock()

#定义飞机初始位置
hero_rect = pygame.Rect(150,300,100,122)

#敌机精灵创建
enemy = GameSprite("./image/enemy0.png")
enemy1 = GameSprite("./image/enemy0.png",2)
enemy_group = pygame.sprite.Group(enemy,enemy1)

#游戏循环
while True:
	#指定循环体内部代码的执行频率   每秒重复60次
	clock.tick(60)
	#监听时间
	event_list = pygame.event.get()
	# if len(event_list)>0:
	# 	print(event_list)
	for event in event_list:
		#判断是否为退出事件
		if event.type == pygame.QUIT:
			print("退出游戏...")
			#卸载所有模块
			pygame.quit()
			exit()
	hero_rect.y -= 1
	if hero_rect.y <=0:
		hero_rect.y = 700
	#将移动前飞机进行遮挡 达到动画效果
	screen.blit(background, (0, 0))
	screen.blit(hero,hero_rect)
	#精灵组调用方法
	enemy_group.update()
	enemy_group.draw(screen)
	pygame.display.update()
	pass
pygame.quit()

程序升级

设置飞机大战的精灵类和常量

这里的update方法主要是在为了后面背景类、敌机类和子弹类中达到可以垂直飞行的效果

#屏幕大小
SCREEN_RECT = pygame.Rect(0,0,480,700)
#刷新帧率
SCREEN_PER_SEC = 60
#创建敌机的定时器常量
CREATE_ENEMY_EVENT = pygame.USEREVENT
#英雄发射子弹事件
HERO_FIRE_EVENT = pygame.USEREVENT + 1

class GameSprite(pygame.sprite.Sprite):
	def __init__(self,image_name,speed=1):
		#调用父类初始化方法
		super().__init__()
		#定义对象属性
		self.image = pygame.image.load(image_name)
		self.rect = self.image.get_rect()
		self.speed = speed
	#更新显示
	def update(self):
		self.rect.y += self.speed

背景类和敌机类

因为想要背景会随着移动,所以在背景类中的init设置了is_alt参数,用来添加背景到原图像的上方,这样就可以达到背景滚动的效果。
在敌机类中对敌机的位置进行判断,如果敌机超过我们预设屏幕y的方位就会使用kill()方法从精灵组中删除,敌机生成的位置和速度采用了random随机数的randint()方法

class Background(GameSprite):
	#游戏背景滚动
	def __init__(self,is_alt=False):
		#调用父类中精灵中的创建 image/rect/speed
		super().__init__("./image/background.png")
		if is_alt:
			self.rect.y = -self.rect.height
	def update(self):
		super().update()
		#如果移出屏幕,将图像移到屏幕上访
		if self.rect.y >= SCREEN_RECT.height:
			self.rect.y = -self.rect.height
class Enemy(GameSprite):
	#敌机精灵
	def __init__(self):
		#1 调用父类方法  创建敌机精灵
		super().__init__("./image/enemy0.png")
		#2 指定敌机初始随机速度
		self.speed = random.randint(1,2)
		#3 指定敌机初始随机位置
		self.rect.bottom = 0
		max_x = SCREEN_RECT.width - self.rect.width
		self.rect.x = random.randint(0,max_x)

	def update(self):
		#!调用父类方法  垂直方向飞行
		super().update()
		#2 判断是否飞出屏幕 如果是,需要从精灵组中删除
		if self.rect.y >= SCREEN_RECT.height:
			print("飞出屏幕,需要从精灵组中删除...")
			#kill方法可以将精灵从精灵族中移出,精灵自动销毁
			self.kill()
	def __del__(self):
		print("敌机死亡 %s" % self.rect)

主机类和子弹类

SCREEN_RECT.centerx是用来保证一开始主机初始在屏幕中央部分,关于主机的y因为在一开始画了一张绘制示意图所以这里应该为屏幕的SCREEN_RECT.bottom减去部分距离。

子弹类中和敌机类同理需要判断是否飞出屏幕范围,如果超过使用kill()方法从精灵组中删除,子弹的初始位置应该是主机的上方,既子弹的x等于主机的x

#主角飞机
class Hero(GameSprite):
	def __init__(self):
		# 调用父类 设置英雄图像和速度
		super().__init__("./image/hero2.png",0)
		# 设置主机位置
		self.rect.centerx = SCREEN_RECT.centerx
		self.rect.bottom = SCREEN_RECT.bottom - 50

		# 子弹精灵组
		self.bullet_group = pygame.sprite.Group()

	def update(self):
		#水平方向移动
		self.rect.x += self.speed

		#控制英雄不能为0
		if self.rect.x < 0:
			self.rect.x =0
		elif self.rect.right > SCREEN_RECT.right:
			self.rect.right = SCREEN_RECT.right
	#子弹发射
	def fire(self):
		print("发射子弹...")
		#创建子弹精灵
		bullet = Bullet()
		#设置子弹位置
		bullet.rect.bottom = self.rect.y-20
		bullet.rect.centerx = self.rect.centerx
		#添加到子弹精灵组中
		self.bullet_group.add(bullet)
#子弹类
class Bullet(GameSprite):
	def __init__(self):
		#调用父类方法 设置子弹图片速度
		super().__init__("./image/bullet1.png",-2)

	def update(self):
		#调用父类方法 让子弹垂直飞行
		super().update()
		#判断子弹是否飞出
		if self.rect.bottom < 0:
			self.kill()
	def __del__(self):
		print("子弹被销毁")

主游戏类

在主类中进行精灵组的创建,背景精灵组的创建是为了达到背景滚动的效果

#精灵组的创建
def __create_sprites(self):
	#创建背景精灵和精灵1组
	bg1 = Background()
	bg2 = Background(True)
	self.back_group = pygame.sprite.Group(bg1,bg2)
	#创建敌机精灵和精灵组
	self.enemy_group = pygame.sprite.Group(
	#创建英雄精灵和精灵组
	self.hero = Hero()
	self.hero_group = pygame.sprite.Group(self.hero)

游戏的初始化

def __init__(self):
	print("游戏初始化")
	#创建游戏窗口
	self.screen = pygame.display.set_mode(SCREEN_RECT.size)
	#创建游戏时钟
	self.clock = pygame.time.Clock()
	self.__create_sprites()
	#敌机生成和主机开火的定时器
	pygame.time.set_timer(CREATE_ENEMY_EVENT,1000)#单位是ms
	pygame.time.set_timer(HERO_FIRE_EVENT,500)

事件监听方法

关于事件的监听过程中,需要对敌机生成和子弹飞行、主机移动指令做出对应反应

def __event_handler(self):
	for event in pygame.event.get():
		if event.type == pygame.QUIT:
			PlaneGame.__game_over()
		elif event.type == CREATE_ENEMY_EVENT:
			print("敌机生成...")
			#创建敌机精灵
			enemy = Enemy()
			#敌机精灵加入精灵组
			self.enemy_group.add(enemy)
		elif event.type == HERO_FIRE_EVENT:
			print("发射子弹...")
			self.hero.fire()
	#飞机移动
	keyss_pressed = pygame.key.get_pressed()
	if keyss_pressed[pygame.K_RIGHT]:
		print("向右移动")
		self.hero.speed = 2
	elif keyss_pressed[pygame.K_LEFT]:
		print("向左移动")
		self.hero.speed = -2
	else:
		self.hero.speed = 0

碰撞检测

对于子弹碰撞敌机和敌机碰撞主机的情况进行判定

#碰撞检测
def __check_collide(self):
	#子弹摧毁敌机
	pygame.sprite.groupcollide(self.hero.bullet_group,self.enemy_group,True,True)
	#敌机撞毁英雄
	enemies = pygame.sprite.spritecollide(self.hero, self.enemy_group, True)
	if len(enemies) > 0:
		self.hero.kill()
		PlaneGame.__game_over()

精灵组更新显示

#精灵更新显示
def __update_sprites(self):
	#背景精灵组
	self.back_group.update()
	self.back_group.draw(self.screen)
	#敌机精灵组
	self.enemy_group.update()
	self.enemy_group.draw(self.screen)
	#主机精灵组
	self.hero_group.update()
	self.hero_group.draw(self.screen)
	#子弹精灵组
	self.hero.bullet_group.update()
	self.hero.bullet_group.draw(self.screen)

游戏的开始与结束

def start_game(self):
	print("游戏开始...")
	while True:
		#1 设置刷新帧率
		self.clock.tick(SCREEN_PER_SEC)
		#2 时间监听
		self.__event_handler()
		#3 碰撞检测
		self.__check_collide()
		#4 更新敌机
		self.__update_sprites()
		#5 更新显示
		pygame.display.update()
@staticmethod
def __game_over():
	print("游戏结束")
	pygame.quit()
	exit()

程序总结

程序中print语句是为了我在运行中进行功能的检测,可以直接注释掉,对于整个程序的运行并无影响。游戏只是简单的规则,主机可以左右移动,敌机会随机从上方垂直下来,敌机撞到主机之后就会游戏结束直接关闭游戏窗体,比如击毁敌机也没有得分这一设置,这些都是可以再对规则进行优化的部分,因为只是为了帮助我熟悉pygame库的功能,所以代码并未写的更加详细,感兴趣的话你可以对代码部分进行更改达到你想要的效果,程序升级部分并未进行太多的文字解释部分,在代码中我保留了我的注释部分方便你对代码进行解读。

程序中用到的素材以及未使用到的音乐都在链接中。

到此这篇关于Pygame库200行代码实现简易飞机大战 的文章就介绍到这了,更多相关Pygame 飞机大战 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Pygame框架实现飞机大战

    本文实例为大家分享了Pygame框架实现飞机大战的具体代码,供大家参考,具体内容如下 飞机大战主游戏类 """ 项目名称:简单飞机大战游戏 基于框架:Pygame 开发日期:2020.07 开发人员:Y 版本:**** """ import sys # 导入内置模块sys 调用sys.exit() import pygame # 导入第三方模块pygame from plane_sprites import * # 导入自定义模块内所有工具 cl

  • pygame实现飞机大战

    本文实例为大家分享了pygame实现飞机大战的具体代码,供大家参考,具体内容如下 运行效果图: import pygame import random import time import os from os import path WIDTH = 480 HEIGHT = 600 FPS = 60#每秒显示多少帧 POWERUP_TIME = 5000 COLOR = (255,174,200) WHITE = (255,255,255) BLACK = (0,0,0) GREEN = (0

  • python之pygame模块实现飞机大战完整代码

    本文实例为大家分享了python之pygame模块实现飞机大战的具体代码,供大家参考,具体内容如下 Python飞机大战步骤: 1.数据区 2.主界面 3.飞船 4.事件监控及边界 5.外星人 6.记分系统 飞机大战效果图: 源码: """ 功能:飞机大战 time:2019/10/3 """ import os import pygame import sys import time from pygame.sprite import Spri

  • pygame实现简易飞机大战

    利用pygame实现了简易版飞机大战.源代码如下: # -*- coding:utf-8 -*- import pygame import sys from pygame.locals import * from pygame.font import * import time import random class Hero(object): #玩家 英雄类 def __init__(self, screen_temp): self.x = 210 self.y = 700 self.life

  • python飞机大战pygame游戏之敌机出场实现方法详解

    本文实例讲述了python飞机大战pygame游戏之敌机出场实现方法.分享给大家供大家参考,具体如下: 目标 使用 定时器 添加敌机 设计 Enemy 类 01. 使用定时器添加敌机 运行 备课代码,观察 敌机的 出现规律: 游戏启动后,每隔 1 秒 会 出现一架敌机 每架敌机 向屏幕下方飞行,飞行 速度各不相同 每架敌机出现的 水平位置 也不尽相同 当敌机 从屏幕下方飞出,不会再飞回到屏幕中 1.1 定时器 在 pygame 中可以使用 pygame.time.set_timer() 来添加

  • python飞机大战pygame碰撞检测实现方法分析

    本文实例讲述了python飞机大战pygame碰撞检测实现方法.分享给大家供大家参考,具体如下: 目标 了解碰撞检测方法 碰撞实现 01. 了解碰撞检测方法 pygame 提供了 两个非常方便 的方法可以实现碰撞检测: pygame.sprite.groupcollide() 两个精灵组 中 所有的精灵 的碰撞检测 groupcollide(group1, group2, dokill1, dokill2, collided = None) -> Sprite_dict 如果将 dokill 设

  • Pygame实战练习之飞机大战游戏

    导语 承载童年的纸飞机你还会叠嘛? 如果你是个80后或者90后,那你应该记得小时候玩的纸飞机. 叠好后,哈口仙气,飞出去,感觉棒棒哒. ​ 虽然是一个极其简单的玩具,但那时候,很多熊孩子能傻傻地玩上一整天. 今天带大家制作一款彩色版本另一个版本的飞机大冒险~ 欢迎阅读往期另一个飞机大战的文章:python开发飞机大战游戏. Are you ready? 一起开启飞机大冒险吧~ ▼▼▼ 正文 首先准备好飞机大冒险的图片: ​ 环境安装:主要游戏模块pygame. pip install pygam

  • python飞机大战pygame游戏框架搭建操作详解

    本文实例讲述了python飞机大战pygame游戏框架搭建操作.分享给大家供大家参考,具体如下: 目标 明确主程序职责 实现主程序类 准备游戏精灵组 01. 明确主程序职责 回顾 快速入门案例,一个游戏主程序的 职责 可以分为两个部分: 游戏初始化 游戏循环 根据明确的职责,设计 PlaneGame 类如下: 提示 根据 职责 封装私有方法,可以避免某一个方法的代码写得太过冗长 如果某一个方法编写的太长,既不好阅读,也不好维护! 游戏初始化 -- init() 会调用以下方法: 游戏循环 --

  • python pygame模块编写飞机大战

    本文实例为大家分享了python pygame模块编写飞机大战的具体代码,供大家参考,具体内容如下 该程序没有使用精灵组,而是用列表存储对象来替代精灵组的动画效果.用矩形对象的重叠来判断相撞事件.该程序可以流畅运行,注释较为详细,希望可以帮助大家. import pygame from pygame.locals import * from sys import exit import time import random # 创建子弹类,把子弹的图片转化为图像对象,设定固定的移动速度 clas

  • Pygame库200行代码实现简易飞机大战

    写在开头,因为这个小游戏的实验主要是帮助我熟悉pygame库的使用,所以游戏的一些地方可能存在不完善处,还望包涵. 安装使用库 pygame简介 pygame是跨平台python模块,专为电子游戏设计,包括图像.声音.建立在SDL基础上,允许实时电子游戏研发而无需被低级语言束缚, 开发者可以把精力放在游戏的架构上. pgame中主要模块介绍 (1) pygame pygame模块会自动导入其它的pygame相关模块. pygame模块包括surface函数, 可以返回一个新的surface 对象

  • JavaScript用200行代码制作打飞机小游戏实例

    我去,我的图片分数被这个录屏软件的水印盖上了,扎心. 这个程序的文件以及代码全部上传到了github 程序下载链接传送门 这是自己第一次通过js写的小游戏,那个时候对象的原理跟结构体的概念不是特别的清晰,所以没用对象来写,所以直接导致后期我对这个程序进行修改的时候出现问题,太过于复杂了,我终于了解什么叫做牵一发动全身了.所以这个程序教会我一定一定要用对象的思想处理以后的问题,尤其是这种带属性明显的东西. 当然你要问我图片怎么来的我只能说都是我自己画的所以这可是原创的原创. 代码部分我是通过一个大

  • 200行代码实现blockchain 区块链实例详解

    了解blockchain的概念很简单(区块链,交易链块):它是分布式的(即不是放置在同一台机器上,不同的网络设备上的)数据库支持主办记录日益增长的名单.但是,这也是容易混淆blockchain与我们试图帮他解决了目标 - 在人们心中的那一刻,这个词是相当强烈的交易,合同或智能cryptocurrency的概念有关. 只有在这里blockchain - 是不是一回事比特币,并理解链块的基本知识比它似乎更容易,尤其是在,它是基于源代码的情况下.在本文中,我们提出了建立与在JavaScript中200

  • java实现简易飞机大战

    目录 整体思路 代码实现 英雄战机类 敌机类 子弹类 图片工具类 游戏窗体类 启动游戏类 运行效果图 本文实例为大家分享了java实现简易飞机大战的具体代码,供大家参考,具体内容如下 整体思路 1.创建游戏窗体,添加面板JPanel,重写JPanel中的paint方法,遍历所有飞机和子弹绘制,用定时器进行重绘,实现动画效果2.添加敌机和发射子弹用的是多线程3.碰撞检测采用的是矩形类Rectangle中的intersects方法 代码实现 用手机查看代码好像只显示62行 英雄战机类 package

  • JavaScript实现简易飞机大战

    本文实例为大家分享了JavaScript实现简易飞机大战的具体代码,供大家参考,具体内容如下 话不多说,直接上代码 <!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale

  • 200行代码轻松实现一个简单的区块链

    英文原文:Lauri Hartikka 区块链的基础概念很简单:一个分布式数据库,存储一个不断加长的 list,list 中包含着许多有序的记录.然而,在通常情况下,当我们谈到区块链的时候也会谈起使用区块链来解决的问题,这两者很容易混淆.像流行的比特币和以太坊这样基于区块链的项目就是这样."区块链"这个术语通常和像交易.智能合约.加密货币这样的概念紧紧联系在一起. 这就令理解区块链变得不必要得复杂起来,特别是当你想理解源码的时候.下面我将通过 200 行 JS 实现的超级简单的区块链来

  • Python 200行代码实现一个滑动验证码过程详解

    前言 做网络爬虫的同学肯定见过各种各样的验证码,比较高级的有滑动.点选等样式,看起来好像挺复杂的,但实际上它们的核心原理还是还是很清晰的,本文章大致说明下这些验证码的原理以及带大家实现一个滑动验证码. 实际上这类验证码的校验是分为两个步骤的: 1.第一步就是前端的校验.一般来说,登录注册页面在点击提交的时候都会伴随着一个表单提交,在表单提交的时候会有 JavaScript 事件的触发.如果加入了验证码,那么在表单提交的时候会多加一个额外的验证,判断这个验证码是否已经成功完成了操作.如果没有的话,

  • 利用不到200行代码写一款属于你自己的js类库

    前言 JavaScript 的核心是支持面向对象的,同时它也提供了强大灵活的 OOP 语言能力.本文将使用面向对象的方式,来教大家用原生js写出一个类似jQuery这样的类库.我们将会学到如下知识点: 闭包:减少变量污染,缩短变量查找范围 自执行函数在对象中的运用 extend的实现原理 如何实现跨浏览器的事件监听 原型链与继承 接下来我会对类库的核心api进行讲解和展示,文章最后后附带类库的完整源码,在我之前的文章<3分钟教你用原生js实现具有进度监听的文件上传预览组件>中也使用了类似的方式

  • 200行Java代码如何实现依赖注入框架详解

    依赖注入介绍 先回顾下依赖注入的概念: 我们常提起的依赖注入(Dependency Injection)和控制反转(Inversion of Control)是同一个概念.具体含义是:当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,在 传统的程序设计过程中,通常由调用者来创建被调用者的实例.但在Spring里,创建被调用者的工作不再由调用者来完成,因此称为控制反转;创建被调用者 实例的工作通常由Spring容器来完成,然后注入调用者,因此也称为

随机推荐