john's tech blog

hope is coming


  • 首页

  • 标签

  • 归档

jad_decompiler

发表于 2017-07-10 | 更新于 2019-05-07

用jad来反编译scala代码,看看版本是否是老版本:

1
jad.exe -r -ff -d src -s java F:\class\**\*.class

反编译的代码会在执行jad程序的目录src下

参考文章:
Windows下利用jad批量反编译class文件
反编译jad的命令使用

scala_mongodb-driver1

发表于 2017-07-06 | 更新于 2019-05-07

前两天研究scala mongodb groupby的问题,又有了另外种解决方案:

在看driver core源码的时候 发现传入的表达式在encode的时候有如下判断:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
final class BuildersHelper {

@SuppressWarnings("unchecked")
static <TItem> void encodeValue(final BsonDocumentWriter writer, final TItem value, final CodecRegistry codecRegistry) {
if (value == null) {
writer.writeNull();
} else if (value instanceof Bson) {
((Encoder) codecRegistry.get(BsonDocument.class)).encode(writer,
((Bson) value).toBsonDocument(BsonDocument.class, codecRegistry),
EncoderContext.builder().build());
} else {
((Encoder) codecRegistry.get(value.getClass())).encode(writer, value, EncoderContext.builder().build());
}
}

private BuildersHelper() {
}
}

发现会判断value是否为Bson,那么想到Filter也是Bson类型,所以有了如下表达式:

1
Filters.and(Filters.all("$code"),Filters.all("$userType"))

scala_mongodb驱动的问题

发表于 2017-07-04 | 更新于 2019-05-07

scala mongodb groupby 多个字段

今天同事问groupby多个字段是怎么写的

然后上$group (aggregation)
看了下,发现要写表达式,看了这篇文章MongoDB aggregate 运用篇 个人总结,发现要像如下写:

1
2
3
4
5
6
7
8

多列group,根据name和status进行多列

db.collection.aggregate([

{$group:{_id:{name:"$name",st:"$status"},count:{$sum:1}}}

]);

那么代码中应该怎么写呢,研究了半天,看到这篇文章MongoDB getCollection with a specific document class

发现我们得从定义mongodbClient开始定义个codeRegistry

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

case class GroupByCode(name:String,code:String) {
// val id: String = _id.toString
}
private[bigdata] val personCodecProvider = Macros.createCodecProvider[GroupByCode]()
private[bigdata] val codecRegistry = fromRegistries( fromProviders(personCodecProvider), DEFAULT_CODEC_REGISTRY )

private[bigdata] val connectionString = new ConnectionString(utils.dbUrl)
private[bigdata] val options = MongoClientSettings
.builder()
.codecRegistry(codecRegistry)
.clusterSettings(ClusterSettings.builder().applyConnectionString(connectionString).build())
.connectionPoolSettings(ConnectionPoolSettings.builder().applyConnectionString(connectionString).build())
.serverSettings(ServerSettings.builder().build()).credentialList(connectionString.getCredentialList)
.sslSettings(SslSettings.builder().applyConnectionString(connectionString).build())
.socketSettings(SocketSettings.builder().applyConnectionString(connectionString).build())
.build()
//private[bigdata] val mongoClient = MongoClient(utils.dbUrl)
private[bigdata] val mongoClient = MongoClient(options)

然后在用的地方直接

1
2
3
val groupBy = group(GroupByCode("$userType","$code"),sum("count", 1))

Await.result(prdb.aggregate(filter(Filters.and(Filters.eq("code", parkCode), Filters.gte("exitDate", date), Filters.lt("exitDate", c.getTime))) :: groupBy :: Nil).toFuture(), read_timeout)

当然mongodb-scala-driver得升级到2.0版才支持caseClassCodec

New in 2.0, the Scala driver allows you to use case classes to represent documents in a collection via the Macros helper. Simple case classes and nested case classes are supported. Hierarchical modelling can be achieve by using a sealed trait and having case classes implement the parent trait.

angular编译服务compileProvider

发表于 2017-07-03 | 更新于 2019-05-07

compileProvider是什么时候注入的

在调用publishExternalAPI的时候注入的:

1
2
3
4
5
6
7
8
9
10
11
12
angularModule('ng', ['ngLocale'], ['$provide',
function ngModule($provide) {
// $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.
$provide.provider({
$$sanitizeUri: $$SanitizeUriProvider
});
//用 injector.invoke时候放入providerCache
$provide.provider('$compile', $CompileProvider)
.directive({

});
});

实际就是执行的

module(name, requires, configFn) {}```方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

configFn参数会在调用的时候就执行
```js
//configFn有可能就是['$provide',function($provide){}]
//config 就是调用configBlocks[insertMethod || 'push']([provider, method, arguments]);
//这里的arguments就是configFn
if (configFn) {
config(configFn);
}
var config = invokeLater('$injector', 'invoke', 'push', configBlocks);


function invokeLater(provider, method, insertMethod, queue) {
if (!queue) queue = invokeQueue;
return function() {
queue[insertMethod || 'push']([provider, method, arguments]);
return moduleInstance;
};
}

queue就是configBlocks.

在runInvokeQueue中就会从providerInjector中获取$injector

1
2
3
4
5
6
7
8
9
10
11
function runInvokeQueue(queue) {
var i, ii;
for (i = 0, ii = queue.length; i < ii; i++) {
var invokeArgs = queue[i],
provider = providerInjector.get(invokeArgs[0]);//此处就是$injector

provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
// invokeArgs[2]此处就是传入的参数数组
//['$provide',function ngModule($provide) {}]
}
}

providerCache在定义的时候就加入了$injector

1
2
3
4
5
6
7
providerInjector = (providerCache.$injector =
createInternalInjector(providerCache, function(serviceName, caller) {
if (angular.isString(caller)) {
path.push(caller);
}
throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
}))

$injector在invoke参数数组的时候去providerCache里找到$provide并且调用它的provider方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function invoke(fn, self, locals, serviceName) {
if (typeof locals === 'string') {
serviceName = locals;
locals = null;
}

//注入参数 $provide
var args = injectionArgs(fn, locals, serviceName);
if (isArray(fn)) { //比如['$scope',function($scope){}]
fn = fn[fn.length - 1];//取数组的最后一个
}

if (!isClass(fn)) {
// http://jsperf.com/angularjs-invoke-apply-vs-switch
// #5388
//比如 var injector = angular.injector(["myModule"]);
//injector.invoke(function(myService){alert(myService.my);});
return fn.apply(self, args);
} else {
args.unshift(null);
return new (Function.prototype.bind.apply(fn, args))();
}
}

angularjs 1.5.8源码解析之service到底干了什么

发表于 2017-07-01 | 更新于 2020-03-23

$provide.service函数

上篇文章创建service最后我们提到了
$provide.service,也就是说模块调用service方法 其实内部到loadModules的时候通过runInvokeQueue
会调用内置的$provide.service函数。

比如我写了个方法如下:

1
2
3
4
var herModule = angular.module('herModule', []);
herModule.service('herService', function() {
this.her = 1;
});

我们一步步来分析它是怎么调用的,首先看第一步

provideCache

我们在之前的文章依赖注入器的产生中看到createInjector的时候会把provideCache传入providerInjector,也就是说我们在调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

```js
function supportObject(delegate) {
return function(key, value) {
//当key是 对象的时候 就把delegate函数放入闭包里
if (isObject(key)) {
//reverseParams 为了适应foreach里调用函数的参数顺序
forEach(key, reverseParams(delegate));// function(value, key) {iteratorFn(key, value);};
} else {
//调用参数delegate方法
return delegate(key, value);
}
};
}
var providerCache = {
//supportObject 都返回一个新函数,内部调用service
$provide: {
service: supportObject(service),
//省略部分代码
}
}

$provide对象不止有service一个属性函数,supportObject 都返回一个新函数,内部调用service。

内部service函数

service函数内部其实就是调用factory函数

1
2
3
4
5
6
7
function service(name, constructor) {
//factoryFn就是个对象数组
return factory(name, ['$injector', function($injector) {
//实例化构造函数,返回实例
return $injector.instantiate(constructor);
}]);
}

内部factory函数

factory函数内部又调用provider函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//factoryFn有可能就是对象数组
//enforce代表是否要有返回值
function factory(name, factoryFn, enforce) {
return provider(name, {
$get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
});
}

//返回一个有返回值的方法而已
function enforceReturnValue(name, factory) {
return function enforcedReturnValue() {
var result = instanceInjector.invoke(factory, this);

return result;
};
}

内部provider函数

1
2
3
4
5
6
7
function provider(name, provider_) {
assertNotHasOwnProperty(name, 'service');
if (isFunction(provider_) || isArray(provider_)) {
provider_ = providerInjector.instantiate(provider_);
}
return providerCache[name + providerSuffix] = provider_;
}

其中最终调用的就是provider方法把一开始的serviceName加上providerSuffix当作对象key,然后{$get:['$injector', function($injector) {return $injector.instantiate(constructor);}]}放入了providerCache。

1…192021…47

John

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