Swoft 2.x 详解Bean
什么是Bean呢?
- Swoft中Bean是一个类的对象实例
- 每个被Swoft管理的PHP对象称之为Bean
- Swoft提供了一个IoC容器来初始化对象和获取对象,用来解决对象之间的依赖管理。
以前当我们要调用一个类的时候是需要先使用new
关键字对类进行实例化后才能使用,现在有了Bean,当Swoft启动的时候就给实例化并一直存在,当你使用时不再需要再去new
,这样可以节省资源。
以JavaBean为例:JavaBean是一种Java语言编写的可重用组件,为了编写JavaBean类必须是具体的和公共的,并且具有无参构造器。JavaBean通过提供符合一致性设计模式的公共方法将内部域暴露成员属性,并通过
set
和get
方法获取。总所周知,属性名符合这种模式,其它Java类可以通过自省(反射)机制发现和操作这些JavaBean的属性。
什么是IoC容器呢?
Swoft为应用提供了一个完整的IoC容器作为依赖管理方案,是Swoft AOP功能、RPC模块等功能的实现基础。
如果对IoC容器不是非常理解的话,请参见《IoC控制反转》。
IoC容器主要解决了三个问题:
- 避免手工管理对象之间的依赖嵌套
- 对象的依赖关系不再在编译期间确定,提供了运行起改变行为的更多弹性。
- 对象可以不再依赖具体实现,而是依赖抽象的接口或是抽象类实现。
什么是Bean容器呢?
容器是一个巨大的工厂,用来存放和管理Bean生命周期。
Bean定义
Bean有两种定义方式:注解、数组配置
- 通过数组定义
- 通过注解定义:注解定义使用PHP文档注解,在类上做标记,通过解析类注解,实现不同的功能。
例如:中间件的定义中
$ vim /app/Middlewares/ActionTestMiddleware.php
<?php
namespace App\Middlewares;use Psr\Http\Server\RequestHandlerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Swoft\Bean\Annotation\Bean;
use Swoft\Http\Message\Middleware\MiddlewareInterface;/*** @Bean()* @uses ActionTestMiddleware*/
class ActionTestMiddleware implements MiddlewareInterface
{public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface{$response = $handler->handle($request);return $response->withAddedHeader('Middleware-Action-Test', 'success');}
}
Bean通过类级别注解@Bean
定义,Bean定义后程序可以直接通过App::getBean()
获取一个Bean实例。
注解使用
@Bean 注解
命名空间:use Swoft\Bean\Annotation\Bean;
源码分析:
$ vim vendor/swoft/framework/src/Bean/Annotation/Bean.php
<?php
namespace Swoft\Bean\Annotation;
/*** bean注解** @Annotation* @Target("CLASS")* @uses Bean*/
class Bean
{/*** bean名称* @var string*/private $name = "";/*** bean类型* @var int*/private $scope = Scope::SINGLETON;/*** referenced bean, default is null* @var string*/private $ref = "";/*** Bean constructor.* @param array $values*/public function __construct(array $values){if (isset($values['value'])) {$this->name = $values['value'];}if (isset($values['name'])) {$this->name = $values['name'];}if (isset($values['scope'])) {$this->scope = $values['scope'];}if (isset($values['ref'])) {$this->ref = $values['ref'];}}/*** 获取bean名称* @return string*/public function getName(): string{return $this->name;}/*** 获取bean类型* @return int*/public function getScope(){return $this->scope;}/*** return name of referenced bean* @return string*/public function getRef(): string{return $this->ref;}
}
打开源码,可以看到Bean构造函数可传入一个关联数组的参数。
public function __construct(array $values)
{if (isset($values['value'])) {$this->name = $values['value'];}if (isset($values['name'])) {$this->name = $values['name'];}if (isset($values['scope'])) {$this->scope = $values['scope'];}if (isset($values['ref'])) {$this->ref = $values['ref'];}
}
构造器参数
name
定义Bean别名,缺省默认类名。scope
注入Bean类型,默认单例Scope::SINGLETON/Scope::PROTOTYPE
。ref
指定引用Bean,用于定义在接口上指定使用哪个接口实现。
使用注意
@Bean
里面只能使用双引号@Bean()
是指注入的Bean名称使用包含命名空间的类名。@Bean("userModel")
和@Bean(name="userModel")
含义是一样的@Bean(name="beanName", scope=Scope::SINGLETON)
默认注入的Bean都是单例,使用scope属性设置其类型。
@Inject
命名空间:use Swoft\Bean\Annotation\Inject;
源码分析:
$ vim vendor/swoft/framework/src/Bean/Annotation/Inject.php
<?php
namespace Swoft\Bean\Annotation;
/*** inject注解** @Annotation* @Target({"PROPERTY","METHOD"})** @uses Inject*/
class Inject
{/*** 注入bean名称* @var string*/private $name = "";/*** Inject constructor.* @param array $values*/public function __construct(array $values){if (isset($values['value'])) {$this->name = $values['value'];}if (isset($values['name'])) {$this->name = $values['name'];}}/*** 获取bean名称* @return string*/public function getName(): string{return $this->name;}
}
构造函数:
name
定义属性注入的Bean名称,缺省属性自动为类型名称。
使用注意:
@Inject
格式与@Bean
基本一样,注意通过注解目前不支持构造函数参数注入。@Inject()
默认注入该属性,对应的包含命名空间的类型名Bean。@Inject(name="${logger}")
和@Inject("${logger}")
注入名称为logger
的Bean到属性@Inject(name="${config.user.stelin.steln}")
注入properties
中配置的值,可以层级和直接直接。
使用示例:
/*** 别名注入.* @Inject("httpRouter")* @var \Swoft\Http\Server\Router\HandlerMapping*/
private $router;/*** 别名注入.* @Inject("application")* @var Application*/
private $application;/*** 注入逻辑层* @Inject()* @var IndexLogic*/
private $logic;
操作Bean
App::getBean()
提供服务定位器式的依赖管理方式,用于可以通过访问服务定位器获取特定的实例,服务定位器解决了“实例构造,实例间依赖管理,具体实现类选择”的问题,并对用户屏蔽相关细节。
Container->set()
方法是App::getBean()
底层实际创建Bean的方法,原理是通过反射和各种注解提供的信息和方法构造Bean的一个代理对象。
use Swoft\App;
App::getBean("name");
//例如
$logic = App::getBean(UserLogic::class);
use Swoft\Core\ApplicationContext;
ApplicationContext::getBean('name');
use Swoft\Bean\BeanFactory;
// App/ApplicationContext/BeanFactory都可从容器中得到Bean
BeanFactory::getBean('name');
use Swoft\Bean\BeanFactory;
// hasBean 某个bean是否存在
BeanFactory::hasBean("name");
Swoft 2.x 详解Bean相关推荐
- Spring第三天,详解Bean的生命周期,学会后让面试官无话可说!
点击下方链接回顾往期 不要再说不会Spring了!Spring第一天,学会进大厂! Spring第二天,你必须知道容器注册组件的几种方式!学废它吊打面试官! 今天讲解Spring中Bean的生命周期. ...
- Spring 详解Bean的后置处理器
Bean的后置处理器详解: Spring当中的后置处理器是Spring体用的一个扩展点,开发者只要去实现,Spring当中的BeanPostProcessor接口,那么就能插手SpringBean实例 ...
- 详解Bean Validation
理性阅读,欢迎探讨 1. Bean Validation是什么? Bean Validation 是一个数据验证规范,属于Java EE 6的子规范,详情参考维基百科,这里不做赘述. 既然是规范,那么 ...
- Spring核心组件详解(Bean、Context、Core)
上篇文章介绍了Spring的有三个核心组件,它们为什么是Spring的核心组件,它们之间啥关系,都代表了啥角色. 下面将详细介绍每个组件内部类的层次关系,以及它们在运行时的时序顺序.我们在使用 Spr ...
- Spring中bean的执行初始化和销毁方法的4种方式详解
一.引入 在java的实际开发过程中,我们可能需要在spring实例化一个bean的过程中,使用到初始化一个对象(bean)后立即初始化(加载)一些数据,或者在销毁一个对象之前进行执行一些事情等等. ...
- theos linux环境,theos安装详解
Go语言异步服务器框架原理和实现 Go语言类库中,有两个官方的服务器框架,一个HTTP,一个是RPC.使用这个两个框架,已经能解决大部分的问题,但是,也有一些需求,这些框架是不够的,这篇文章,我们先分 ...
- Spring——三级缓存解决循环依赖详解
三级缓存解决循环依赖详解 一.什么是三级缓存 二.三级缓存详解 Bean实例化前 属性赋值/注入前 初始化后 总结 三.怎么解决的循环依赖 四.不用三级缓存不行吗 五.总结 一.什么是三级缓存 就是在 ...
- Springboot@Configuration和@Bean详解
Springboot@Configuration和@Bean详解 一.@Configuration @Target({ElementType.TYPE}) @Retention(RetentionPo ...
- java spring bean配置文件_Spring基于xml文件配置Bean过程详解
这篇文章主要介绍了spring基于xml文件配置Bean过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 通过全类名来配置: class:be ...
最新文章
- 不是广告--如何学Java,我说点不太一样的学习方式
- NOIP2008 双栈排序
- java main方法调用非静态方法_java中main函数怎么调用外部非static方法
- linux运维(五)
- 无线通信技术协议-Zigbee 3.0
- 数据处理——数据编码
- Content Provider的启动过程
- 如何利用MongoDB打造TOP榜小程序
- jmeter简单使用教程
- T430s BIOS白名单破解
- linux中原子量的学习和理解
- 怎么看待小公司的规章制度?
- 自定义关机计算机,win7自定义定时关机设置方法是什么
- 论文:CenterNet: Keypoint Triplets for Object Detection 阅读笔记
- 课堂派考试可以切屏吗_雨课堂考试可以切屏吗?能切出去搜答案吗
- Orion2 CDM 操作系统-操作部分20211206
- 【设计模式03】 建造者模式
- 人类会被人工智能打败吗?
- 「 C/C++疑难杂症 」warning: ISO C++ forbids converting a string constant to ‘CHAR*’ {aka ‘char*’} [-Wwrite
- springboot返回时间有错解决方案