john's tech blog

hope is coming


  • 首页

  • 标签

  • 归档

spring5.1.1源码剖析之AbstractAutowireCapableBeanFactory

发表于 2019-05-29 | 更新于 2019-07-09

关于AbstractAutowireCapableBeanFactory

源码文档中是这么说的:

Abstract bean factory superclass that implements default bean creation,
with the full capabilities specified by the {@link RootBeanDefinition} class.
Implements the {@link org.springframework.beans.factory.config.AutowireCapableBeanFactory}
interface in addition to AbstractBeanFactory’s {@link #createBean} method.

org.springframework.beans.factory.support.DefaultListableBeanFactory 这个很重要的类继承自
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory

简单点说这个beanfactory做了三样事情

  1. 实现默认bean创建,bean拥有RootBeanDefinition类指定的所有能力
  2. 实现了AutowireCapableBeanFactory接口。
  3. 实现了AbstractBeanFactory的createBean方法。

javascript基础知识之bind

发表于 2019-05-25

JavaScript bind方法使用

1
2
3
4
5
6
7
8
9
var obj = {
myFun:function(){
console.log(this.name);
}
}
var db = {
name :"john"
}
  obj.myFun.bind(db)();   //john

以上出了bind 方法后面多了个 () 外 ,结果返回都一致!
由此得出结论,bind 返回的是一个新的函数,你必须调用它才会被执行

JavaScript bind多次绑定

昨天看到掘金小册 前端面试之道时 看到bind的特殊用法,之前不知道有这么一回事,所以在此记录下.
下面转载自原文。

如果对一个函数进行多次 bind,那么上下文会是什么呢?

1
2
3
let a = {}
let fn = function () { console.log(this) }
fn.bind().bind(a)() // => ?

如果你认为输出结果是 a,那么你就错了,其实我们可以把上述代码转换成另一种形式

1
2
3
4
5
6
7
// fn.bind().bind(a) 等于
let fn2 = function fn1() {
return function() {
return fn.apply()
}.apply(a)
}
fn2()

可以从上述代码中发现,不管我们给函数 bind 几次,fn 中的 this 永远由第一次 bind 决定,所以结果永远是 window。

1
2
3
4
5
let a = { name: 'yck' }
function foo() {
console.log(this.name)
}
foo.bind(a)() // => 'yck'

参考资料:

  1. 前端面试之道

angular源码剖析之Provider系列-$http

发表于 2019-05-22 | 更新于 2019-05-24

前言

虽然现在angular.js已经不怎么流行,也逐渐被react,vue等主流框架取代,但是angular.js中的一些
设计我觉得非常值得学习,我们不仅仅要跟随潮流,也得了解曾经优秀流行的框架是怎么设计的,为什么要这么
设计,这样我觉得学习新技术才会思路更清晰,才能更快上手。
我们在工作中为了尽快完成领导交给我们的任务不得不去熟悉使用现有框架提供给我们的福利,
却忽略了基础知识或者说底层技术的掌握,框架就是把各种基础函数和技术封装好让软件开发的效率提升,所以现在我们的很多开发人员只停留在使用层面却
不去想这个功能建立在哪些基础知识点上,

$http简介

先来看官方文档的简介:
The $http service is a core AngularJS service that facilitates communication with
the remote HTTP servers via the browser’s XMLHttpRequest object or via JSONP.

$http服务是AngularJs的核心服务,是通过浏览器的XMLHttpRequest对象或者JSONP来跟远程http服务
进行通信的.也就是说$http内部必然是通过封装的ajax来完成他的设计的。
$http是基于$q服务暴露出来的deferred/promise api,所以要知道$http的高级使用得熟悉这些api.

$http核心

1.扩展配置
2.把请求拦截器和响应拦截器放入promise链
3.把核心方法serverRequest放入promise链

核心方法里最终返回了promise对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
function $http(requestConfig) {

//忽略部分代码
//扩展了requestConfig
var config = extend({
method: 'get',
transformRequest: defaults.transformRequest,
transformResponse: defaults.transformResponse,
paramSerializer: defaults.paramSerializer
}, requestConfig);

config.headers = mergeHeaders(requestConfig);
config.method = uppercase(config.method);
config.paramSerializer = isString(config.paramSerializer) ?
$injector.get(config.paramSerializer) : config.paramSerializer;

//请求拦截器
var requestInterceptors = [];
//响应拦截器
var responseInterceptors = [];
//调用$q的静态方法when
var promise = $q.when(config);

// apply interceptors
//加入拦截器
forEach(reversedInterceptors, function(interceptor) {
if (interceptor.request || interceptor.requestError) {
//unshift在顶部插入
//unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。
//随后在chain的时候一次取出两个元素
requestInterceptors.unshift(interceptor.request, interceptor.requestError);
}
if (interceptor.response || interceptor.responseError) {
//push在尾部插入
//push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度。
responseInterceptors.push(interceptor.response, interceptor.responseError);
}
});

promise = chainInterceptors(promise, requestInterceptors);
//核心请求放入promise链
promise = promise.then(serverRequest);
promise = chainInterceptors(promise, responseInterceptors);

//忽略部分代码
return promise;
}

serverRequest方法

serverRequest调用sendReq方法发送请求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//放在promise里
function serverRequest(config) {
//配置的请求头
var headers = config.headers;
//转换请求数据
var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest);

// strip content-type if data is undefined
if (isUndefined(reqData)) {
forEach(headers, function(value, header) {
if (lowercase(header) === 'content-type') {
delete headers[header];
}
});
}

if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {
config.withCredentials = defaults.withCredentials;
}

//关键的步骤 发送请求
// send request
//返回新的promise供外部调用
return sendReq(config, reqData).then(transformResponse, transformResponse);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
function sendReq(config, reqData) {
//创建defrred对象
var deferred = $q.defer(),
promise = deferred.promise,
cache,
cachedResp,
reqHeaders = config.headers,
//构造请求url
url = buildUrl(config.url, config.paramSerializer(config.params));

//
$http.pendingRequests.push(config);
promise.then(removePendingReq, removePendingReq);
//配置了cache属性且是get 方法时
if ((config.cache || defaults.cache) && config.cache !== false &&
(config.method === 'GET' || config.method === 'JSONP')) {
cache = isObject(config.cache) ? config.cache
: isObject(defaults.cache) ? defaults.cache
: defaultCache;
}

if (cache) {
//cachedResp是个promise对象
cachedResp = cache.get(url);
//如果存在缓存那么就存缓存中获取响应结果
if (isDefined(cachedResp)) {
if (isPromiseLike(cachedResp)) {
// cached request has already been sent, but there is no response yet
cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult);
} else {
// serving from cache
if (isArray(cachedResp)) {
resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]);
} else {
resolvePromise(cachedResp, 200, {}, 'OK');
}
}
} else {
// put the promise for the non-transformed response into cache as a placeholder
cache.put(url, promise);
}
}

// if we won't have the response in cache, set the xsrf headers and
// send the request to the backend
if (isUndefined(cachedResp)) {
var xsrfValue = urlIsSameOrigin(config.url)
? $$cookieReader()[config.xsrfCookieName || defaults.xsrfCookieName]
: undefined;
if (xsrfValue) {
reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;
}
//done函数里调用了promise
//调用httpBackend
//事件处理器
//上传事件处理器
//done方法在httpBackend中回调
$httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,
config.withCredentials, config.responseType,
createApplyHandlers(config.eventHandlers),
createApplyHandlers(config.uploadEventHandlers));
}
//返回promise函数
return promise;

function createApplyHandlers(eventHandlers) {
if (eventHandlers) {
var applyHandlers = {};
forEach(eventHandlers, function(eventHandler, key) {
applyHandlers[key] = function(event) {
if (useApplyAsync) {
$rootScope.$applyAsync(callEventHandler);
} else if ($rootScope.$$phase) {
callEventHandler();
} else {
$rootScope.$apply(callEventHandler);
}

function callEventHandler() {
eventHandler(event);
}
};
});
return applyHandlers;
}
}

//重要的一步
//注册到$httpBackend()方法
//缓存响应
//处理原始$http promise
//调用$apply
/**
* Callback registered to $httpBackend():
* - caches the response if desired
* - resolves the raw $http promise
* - calls $apply
*/

//status 响应状态 response 响应对象
//headersString 响应头
//statusText 状态文本
function done(status, response, headersString, statusText) {
}

}

angular源码剖析之启动流程图

发表于 2019-05-20

nodejs知识点整理

发表于 2019-05-16 | 更新于 2019-05-30
  1. 干货 | 浅谈Node.js在携程的应用
  2. npm install 版本号^的坑
  3. 使用 Puppeteer 导出声享 PPT
  4. 『Carlo』 一个新的 Electron ?
  5. 关于npm audit fix
  6. MAC终端安装指定版本node
  7. macOS工具使用篇之–Homebrew
  8. “yarn global list” doesn’t list globally installed packages that don’t have binaries

  9. Node的“字节码增强技术”你了解吗?
    iltorb@1.3.10

  10. 道路千万条,安全第一条——一次服务器被入侵的处理经过

1…91011…47

John

232 日志
43 标签
GitHub Twitter
欢迎关注我的公众号:沉迷Spring
© 2023 johnwonder
由 Hexo 强力驱动 v3.2.0
|
主题 – NexT.Pisces v7.1.1
|
0%