-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
1165 lines (548 loc) · 119 KB
/
index.html
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!doctype html>
<html class="theme-next muse use-motion">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<link href="/vendors/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css"/>
<link href="//fonts.googleapis.com/css?family=Lato:300,300italic,400,400italic,700,700italic&subset=latin,latin-ext" rel="stylesheet" type="text/css">
<link href="/vendors/font-awesome/css/font-awesome.min.css?v=4.4.0" rel="stylesheet" type="text/css" />
<link href="/css/main.css?v=5.0.1" rel="stylesheet" type="text/css" />
<meta name="keywords" content="kevinjom, KevinFan, Java, Spring, Ruby" />
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?v=5.0.1" />
<meta name="description">
<meta property="og:type" content="website">
<meta property="og:title" content="KevinFan's BLOG">
<meta property="og:url" content="http://kevinjom.github.io/index.html">
<meta property="og:site_name" content="KevinFan's BLOG">
<meta property="og:description">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="KevinFan's BLOG">
<meta name="twitter:description">
<script type="text/javascript" id="hexo.configuration">
var NexT = window.NexT || {};
var CONFIG = {
scheme: 'Muse',
sidebar: {"position":"left","display":"post"},
fancybox: true,
motion: true,
duoshuo: {
userId: 0,
author: 'Author'
}
};
</script>
<title> KevinFan's BLOG </title>
</head>
<body itemscope itemtype="http://schema.org/WebPage" lang="en">
<div class="container one-collumn sidebar-position-left
">
<div class="headband"></div>
<header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
<div class="header-inner"><div class="site-meta ">
<div class="custom-logo-site-title">
<a href="/" class="brand" rel="start">
<span class="logo-line-before"><i></i></span>
<span class="site-title">KevinFan's BLOG</span>
<span class="logo-line-after"><i></i></span>
</a>
</div>
<p class="site-subtitle">I love freedom for no reason</p>
</div>
<div class="site-nav-toggle">
<button>
<span class="btn-bar"></span>
<span class="btn-bar"></span>
<span class="btn-bar"></span>
</button>
</div>
<nav class="site-nav">
<ul id="menu" class="menu">
<li class="menu-item menu-item-home">
<a href="/" rel="section">
<i class="menu-item-icon fa fa-home fa-fw"></i> <br />
Home
</a>
</li>
<li class="menu-item menu-item-archives">
<a href="/archives" rel="section">
<i class="menu-item-icon fa fa-archive fa-fw"></i> <br />
Archives
</a>
</li>
<li class="menu-item menu-item-tags">
<a href="/tags" rel="section">
<i class="menu-item-icon fa fa-tags fa-fw"></i> <br />
Tags
</a>
</li>
</ul>
</nav>
</div>
</header>
<main id="main" class="main">
<div class="main-inner">
<div class="content-wrap">
<div id="content" class="content">
<section id="posts" class="posts-expand">
<article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2016/05/18/effetive-ruby-tldr-part2/" itemprop="url">
effetive-ruby-tldr-part2
</a>
</h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">Posted on</span>
<time itemprop="dateCreated" datetime="2016-05-18T19:27:16+08:00" content="2016-05-18">
2016-05-18
</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h2 id="11-Create-namespace-by-nesting-code-in-Module"><a href="#11-Create-namespace-by-nesting-code-in-Module" class="headerlink" title="#11. Create namespace by nesting code in Module"></a>#11. Create namespace by nesting code in Module</h2><ul>
<li>Use modules to create namespece by nesting definiton inside them.</li>
<li>Mirror you namesapece structure to your dir structure.</li>
<li>Use <code>::</code> to fully qualify a top-level constant.</li>
</ul>
<h2 id="12-Understand-the-Different-Flavors-of-Equality"><a href="#12-Understand-the-Different-Flavors-of-Equality" class="headerlink" title="#12. Understand the Different Flavors of Equality"></a>#12. Understand the Different Flavors of Equality</h2><ul>
<li>Use <code>==</code> to test if two obejcts represent the same value.</li>
</ul>
<figure class="highlight ruby"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1</span> == <span class="string">`1.0`</span> <span class="comment"># true</span></span><br></pre></td></tr></table></figure>
<ul>
<li>Use <code>eql?</code> to test if two objects represent the same value and also the same<br>type.</li>
</ul>
<figure class="highlight ruby"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1</span> == <span class="string">`1.0`</span> <span class="comment"># false</span></span><br><span class="line"><span class="number">1</span> == <span class="number">1</span> <span class="comment"># true</span></span><br></pre></td></tr></table></figure>
<ul>
<li><p>Use <code>equal?</code> to test if two objects are the same object (with same object_id),<br>so <strong>never</strong> override this method.</p>
</li>
<li><p><code>===</code> - <code>== || =~ || is_a?</code></p>
</li>
</ul>
<figure class="highlight ruby"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">'a'</span>===<span class="string">'a'</span> <span class="comment">#true - 'a'=='a'</span></span><br><span class="line">/a/i===<span class="string">'Abc'</span> <span class="comment">#0 - /a/i =~ 'Abc'</span></span><br><span class="line"><span class="constant">String</span>===<span class="string">'a'</span> <span class="comment">#true - 'a'.is_a? String</span></span><br></pre></td></tr></table></figure>
<h2 id="13-Implement-Comparison-via-lt-gt-and-the-Comparable-Module"><a href="#13-Implement-Comparison-via-lt-gt-and-the-Comparable-Module" class="headerlink" title="#13. Implement Comparison via <=> and the Comparable Module"></a>#13. Implement Comparison via <=> and the Comparable Module</h2><ul>
<li>Implement object ordering by defining a “<=>” operator and including the Comparable module.</li>
<li>The “<=>” operator should return nil if the left operand can’t be compared with the right.</li>
<li>If you implement “<=>” for a class you should consider aliasing eql? to “==”, especially if you want instances to be usable as hash keys. In which case you should also override the hash method. NOTE. <code>==</code> does <strong>NOT</strong> test type equity.</li>
</ul>
<h2 id="14-Share-Private-State-Through-Protected-Methods"><a href="#14-Share-Private-State-Through-Protected-Methods" class="headerlink" title="#14. Share Private State Through Protected Methods"></a>#14. Share Private State Through Protected Methods</h2><ul>
<li>Protected methods can be called with an explicit receiver from objects of the same class</li>
</ul>
<h2 id="15-Prefer-Class-Instance-Variables-to-Class-Variables"><a href="#15-Prefer-Class-Instance-Variables-to-Class-Variables" class="headerlink" title="#15. Prefer Class Instance Variables to Class Variables"></a>#15. Prefer Class Instance Variables to Class Variables</h2><h2 id="16-Duplicate-Collections-Passed-as-Arguments-Before-Mutating-Them"><a href="#16-Duplicate-Collections-Passed-as-Arguments-Before-Mutating-Them" class="headerlink" title="#16. Duplicate Collections Passed as Arguments Before Mutating Them"></a>#16. Duplicate Collections Passed as Arguments Before Mutating Them</h2><ul>
<li>Method arguments in Ruby are passed as references, not values</li>
<li>The dup and clone methods only create shallow copies.</li>
</ul>
<figure class="highlight ruby"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">User</span></span></span><br><span class="line"> <span class="keyword">attr_accessor</span> <span class="symbol">:name</span></span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">initialize</span><span class="params">(name)</span></span></span><br><span class="line"> <span class="variable">@name</span> = name</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line">u1 = <span class="constant">User</span>.new <span class="string">'kevin'</span></span><br><span class="line">u2 = <span class="constant">Use</span>.new <span class="string">'others'</span></span><br><span class="line"></span><br><span class="line">arr = [u1, u2]</span><br><span class="line">arr2 = arr.dup</span><br><span class="line"></span><br><span class="line">u2.name = <span class="string">'new name'</span></span><br><span class="line"></span><br><span class="line">arr == arr2 <span class="comment"># true</span></span><br></pre></td></tr></table></figure>
<ul>
<li>For most objects, Marshal can be used to create deep copies when needed.</li>
</ul>
<figure class="highlight ruby"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">arr3 = <span class="constant">Marshal</span>.load <span class="constant">Marshal</span>.dump arr</span><br><span class="line"></span><br><span class="line">u2.name = <span class="string">'new new'</span></span><br><span class="line"></span><br><span class="line">arr == arr3 <span class="comment">#false</span></span><br></pre></td></tr></table></figure>
<h2 id="17-Use-the-Array-Method-to-Convert-nil-and-Scalar-Objects-into-Arrays"><a href="#17-Use-the-Array-Method-to-Convert-nil-and-Scalar-Objects-into-Arrays" class="headerlink" title="#17. Use the Array Method to Convert nil and Scalar Objects into Arrays"></a>#17. Use the Array Method to Convert nil and Scalar Objects into Arrays</h2><figure class="highlight ruby"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="constant">Array</span>(<span class="keyword">nil</span>) <span class="comment"># []</span></span><br><span class="line"><span class="constant">Array</span>([<span class="keyword">nil</span>, <span class="symbol">:a</span>]) <span class="comment"># [nil, :a]</span></span><br><span class="line"><span class="constant">Array</span>({<span class="symbol">a:</span><span class="number">12</span>,<span class="symbol">b:</span><span class="number">323</span>} <span class="comment">#[:a, :b]</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Array() - First tries to call Array#to_ary on arg, then Array#to_a.</span></span><br></pre></td></tr></table></figure>
<h2 id="18-Consider-Set-for-Efficient-Element-Inclusion-Checking"><a href="#18-Consider-Set-for-Efficient-Element-Inclusion-Checking" class="headerlink" title="#18. Consider Set for Efficient Element Inclusion Checking"></a>#18. Consider Set for Efficient Element Inclusion Checking</h2><ul>
<li><code>require 'set'</code> before you use it.</li>
</ul>
<h2 id="19-Know-How-to-Fold-Collections-with-reduce"><a href="#19-Know-How-to-Fold-Collections-with-reduce" class="headerlink" title="#19. Know How to Fold Collections with reduce"></a>#19. Know How to Fold Collections with reduce</h2><ul>
<li>Always use a starting value for the accumulator.</li>
</ul>
<figure class="highlight ruby"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>].reduce(<span class="number">0</span>,<span class="symbol">:+</span>) <span class="comment">#6</span></span><br></pre></td></tr></table></figure>
<ul>
<li>The block given to reduce should always return an accumulator. It’s fine to mutate the current accumulator, just remember to return it from the block”.</li>
</ul>
<figure class="highlight ruby"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">[<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>].reduce({}) <span class="keyword">do</span> |map, e|</span><br><span class="line"> map[e.to_s] = e</span><br><span class="line"> map</span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure>
<h2 id="20-Consider-Using-a-Default-Hash-Value"><a href="#20-Consider-Using-a-Default-Hash-Value" class="headerlink" title="#20. Consider Using a Default Hash Value"></a>#20. Consider Using a Default Hash Value</h2><h2 id="21-Prefer-Delegation-to-Inheriting-from-Collection-Classes"><a href="#21-Prefer-Delegation-to-Inheriting-from-Collection-Classes" class="headerlink" title="#21. Prefer Delegation to Inheriting from Collection Classes"></a>#21. Prefer Delegation to Inheriting from Collection Classes</h2>
</div>
<div>
</div>
<div>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2016/05/12/effetive-ruby-tldr-part1/" itemprop="url">
Effetive Ruby TLDR - part1
</a>
</h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">Posted on</span>
<time itemprop="dateCreated" datetime="2016-05-12T23:10:28+08:00" content="2016-05-12">
2016-05-12
</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h2 id="“Accustoming-Yourself-to-Ruby”"><a href="#“Accustoming-Yourself-to-Ruby”" class="headerlink" title="“Accustoming Yourself to Ruby”"></a>“Accustoming Yourself to Ruby”</h2><h3 id="1-Understand-What-Ruby-Considers-To-Be-True"><a href="#1-Understand-What-Ruby-Considers-To-Be-True" class="headerlink" title="#1. Understand What Ruby Considers To Be True"></a>#1. Understand What Ruby Considers To Be True</h3><ul>
<li>Every value is <code>true</code>expect <code>false</code> and <code>nil</code>.</li>
<li>The number <code>0</code> is <code>ture</code> in Ruby.</li>
<li>Check if a value is nil with <code>value#nil?</code>.</li>
</ul>
<h3 id="2-Treat-All-Objects-As-If-They-Could-Be-nil"><a href="#2-Treat-All-Objects-As-If-They-Could-Be-nil" class="headerlink" title="#2. Treat All Objects As If They Could Be nil"></a>#2. Treat All Objects As If They Could Be nil</h3><ul>
<li>Only <code>nil.nil?</code> returns <code>true</code>.</li>
<li>You can cast a nil to a empty string with <code>nil.to_s</code> or to a int with<br><code>nil.to_i</code>.</li>
</ul>
<h3 id="3-Avoid-Ruby’s-Cryptic-Perlisms"><a href="#3-Avoid-Ruby’s-Cryptic-Perlisms" class="headerlink" title="#3. Avoid Ruby’s Cryptic Perlisms"></a>#3. Avoid Ruby’s Cryptic Perlisms</h3><ul>
<li>Prefer <code>String#match</code> to <code>str =~</code>.</li>
<li>Don’t modify global variables unless you must do.</li>
</ul>
<h3 id="4-Be-Aware-That-Constants-Are-Mutable"><a href="#4-Be-Aware-That-Constants-Are-Mutable" class="headerlink" title="#4. Be Aware That Constants Are Mutable"></a>#4. Be Aware That Constants Are Mutable</h3><ul>
<li>Always <code>freeze</code> constant values to prevent them to be mutated.</li>
<li>To prevent assigning new values to existing constants, freeze the module they<br>are defined in.</li>
</ul>
<h3 id="5-Pay-attention-to-runtime-warnings"><a href="#5-Pay-attention-to-runtime-warnings" class="headerlink" title="#5. Pay attention to runtime warnings"></a>#5. Pay attention to runtime warnings</h3><ul>
<li>Use the <code>-w</code> CLI option to enable compile and runtime warnings. Or make it<br>part of the <code>RUBYOPT</code> env variable.</li>
</ul>
<h2 id="Classes-Objects-and-Modules"><a href="#Classes-Objects-and-Modules" class="headerlink" title="Classes, Objects and Modules"></a>Classes, Objects and Modules</h2><h3 id="6-Know-how-ruby-build-inheritance-hierarchies"><a href="#6-Know-how-ruby-build-inheritance-hierarchies" class="headerlink" title="#6. Know how ruby build inheritance hierarchies"></a>#6. Know how ruby build inheritance hierarchies</h3><ul>
<li>Method lookup algo - move right, then go up, that means when you clll a method<br><code>foo.bar</code>, you move to the right, find the class of the object <code>foo</code>, if you<br>find <code>bar</code> in <code>foo</code>‘s class, then invoke it, or move to <code>foo</code>‘s superclass, do<br>the same thing.</li>
<li>If no method has been found, <code>method_missing</code> will be called with the same<br>algo as above.</li>
<li>Module are classes too. Including modules silently creates singleton classes<br>which are inserted into the hierarchy above the including class.</li>
<li>Class methods are just instance methods of the class’s metaclass</li>
</ul>
<h3 id="7-Be-Aware-of-the-Different-Behaviors-of-super"><a href="#7-Be-Aware-of-the-Different-Behaviors-of-super" class="headerlink" title="#7. Be Aware of the Different Behaviors of super"></a>#7. Be Aware of the Different Behaviors of super</h3><ul>
<li>Use <code>super</code> to call the overridden method.</li>
<li>Use <code>super</code> with no args and no parentheses is equivalent to passing it all of<br>the arguments which were given to the enclosing method.</li>
<li>Use to <code>super()</code> to call overriden method withoug passing any arguments.</li>
</ul>
<h3 id="8-Invoke-super-When-Initializing-Sub-classes"><a href="#8-Invoke-super-When-Initializing-Sub-classes" class="headerlink" title="#8. Invoke super When Initializing Sub-classes"></a>#8. Invoke super When Initializing Sub-classes</h3><ul>
<li>Ruby doesn’t automatically call the <code>initialize</code> method in the superclass when<br>creating objects from a subclass</li>
<li>Call the overriden <code>initialize</code> method explicitly with <code>super</code></li>
</ul>
<h3 id="9-Be-Alert-for-Ruby’s-Most-Vexing-Parse"><a href="#9-Be-Alert-for-Ruby’s-Most-Vexing-Parse" class="headerlink" title="#9. Be Alert for Ruby’s Most Vexing Parse"></a>#9. Be Alert for Ruby’s Most Vexing Parse</h3><ul>
<li>Setter method must have a reciever, inside the class that defines it, the<br>receiver should be <code>self</code></li>
<li>Avoid using <code>self</code> when call other methods inside a class.</li>
</ul>
<h3 id="10-Prefer-Struct-to-Hash-for-Structured-Data"><a href="#10-Prefer-Struct-to-Hash-for-Structured-Data" class="headerlink" title="#10. Prefer Struct to Hash for Structured Data"></a>#10. Prefer Struct to Hash for Structured Data</h3><ul>
<li>When dealing with structured data which doesn’t quite justify a new class<br>prefer using Struct to Hash.</li>
<li>Assign the return value of Struct::new to a constant and treat that constant<br>like a class.</li>
</ul>
<h4 id="Demo"><a href="#Demo" class="headerlink" title="Demo"></a>Demo</h4><figure class="highlight ruby"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="constant">User</span> = <span class="constant">Struct</span>.new(<span class="symbol">:name</span>, <span class="symbol">:age</span>) <span class="comment"># User.class = Class</span></span><br><span class="line">user = <span class="constant">User</span>.new(<span class="string">'kevin'</span>, <span class="number">18</span>)</span><br><span class="line">puts user.name</span><br><span class="line">user.age = <span class="number">22</span></span><br></pre></td></tr></table></figure>
</div>
<div>
</div>
<div>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2016/04/13/hexo-plus-ghpages/" itemprop="url">
Hexo + Github Pages = 你的博客
</a>
</h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">Posted on</span>
<time itemprop="dateCreated" datetime="2016-04-13T23:28:37+08:00" content="2016-04-13">
2016-04-13
</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h3 id="曾经的故事"><a href="#曾经的故事" class="headerlink" title="曾经的故事"></a>曾经的故事</h3><p>最近又想搞搞博客了,之前使用过 <code>Hexo</code>,印象不错,但是唯一有一个问题就是我当时是使用<code>hexo d</code>来把<code>hexo g</code>生成的<code>public</code>目录下的内容放到github 上的,后来因为换电脑等等原因,源文件已经找不到了。</p>
<h3 id="有时候也很笨"><a href="#有时候也很笨" class="headerlink" title="有时候也很笨"></a>有时候也很笨</h3><p>因此,觉得这个东西不好用,<code>hexo d</code>只是部署生成的表态文件到 github,而不会把源文件也放到 github,这样如果我换电脑或者使用其它电脑时就很不方便,我还得再建一个 repo 去维护这个东西,所以决定尝试一下<code>jekyll</code></p>
<h3 id="为什么放弃jekyll"><a href="#为什么放弃jekyll" class="headerlink" title="为什么放弃jekyll"></a>为什么放弃<code>jekyll</code></h3><p>首先我得说下我对静态博客工具的态度:</p>
<ul>
<li>不要很难上手,因为我不想在这上面花太多功夫</li>
<li>可以与github pages集成</li>
<li>支持主题,并且主题要很容易切换 (虽然博客的重点是内容而非表面,但是人都有爱美之心,并且容易喜新厌旧)</li>
</ul>
<p>我想<code>jekyll</code>与 github pages 是天然集成的,并且它还有无数非常美丽的主题,但是,它的主题切换就不像<code>hexo</code>那么的方便了,当然有可能是我没有搞清楚,但是, anyway,我不想在这上面花太多功夫,所以,决定回归<code>hexo</code>.</p>
<h3 id="如何重回-hexo"><a href="#如何重回-hexo" class="headerlink" title="如何重回 hexo"></a>如何重回 <code>hexo</code></h3><h4 id="versoin-control你的源代码"><a href="#versoin-control你的源代码" class="headerlink" title="versoin control你的源代码"></a>versoin control你的源代码</h4><p>对于上面我说的<code>hexo</code>的源代码如何保存的问题,我现在的做法是这样的<br>建立一个新的分支<code>blog/hexo</code>, 这里面就放着从<code>hexo init</code>到后面各种修改的内容,但是下面这几个文件我觉得是没有必要提交的,所以,可以把它们加到<code>.gitignore</code>文件中</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">.deploy_git/ node_modules/ public/ themes/ db.json</span><br></pre></td></tr></table></figure>
<p>这里特别要注意的是<code>themes</code>,因为这下面放了你下载的主题,你是很有可能对这些主题进行自定义配置的,所以我的想法是创建一个相对应主题的配置文件,然后把<code>themes/bla-theme/bla.file</code> 链接到你新建的配置文件。(当然了,我还没来得及弄)</p>
<h4 id="部署你的网站"><a href="#部署你的网站" class="headerlink" title="部署你的网站"></a>部署你的网站</h4><p><code>hexo</code>提供了<code>hexo-deployer-git</code>可以让你只用一句命令<code>hexo d</code>就可以将你的网站部署到 github pages 上, 具体请看<a href="https://hexo.io/docs/deployment.html" target="_blank" rel="external">官方文档</a></p>
<p>在使用这个工具之前,你需要确保</p>
<ol>
<li><p>你已经配置了你的 git repo 信息到<code>_config.yml</code>中,示例如下:</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">deploy: type: git repo: git@github.com:kevinjom/kevinjom.github.io.git branch: master</span><br></pre></td></tr></table></figure>
</li>
<li><p>先执行<code>hexo g</code></p>
</li>
</ol>
<p>当然了,如果嫌麻烦,你可以写一个简单的脚本。下面是一个例子</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="shebang">#!/bin/bash</span><br><span class="line"></span></span><br><span class="line"><span class="built_in">set</span> <span class="operator">-e</span></span><br><span class="line"></span><br><span class="line">PROG=$(basename <span class="variable">$0</span>)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="title">usage</span></span>() {</span><br><span class="line"> <span class="built_in">echo</span> <span class="string">"<span class="variable">$PROG</span> <commit message>"</span></span><br><span class="line"> <span class="built_in">exit</span> <span class="number">1</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">[[ -n <span class="variable">$1</span> ]] || usage</span><br><span class="line"></span><br><span class="line">git stash</span><br><span class="line">git pull origin blog/hexo --rebase</span><br><span class="line">git stash pop || <span class="built_in">echo</span> <span class="string">"no stash to pop"</span></span><br><span class="line">git add .</span><br><span class="line">git commit -m <span class="string">"<span class="variable">$1</span>"</span></span><br><span class="line"></span><br><span class="line">hexo g</span><br><span class="line">hexo d</span><br></pre></td></tr></table></figure>
<h3 id="自定义域名过期了怎么办"><a href="#自定义域名过期了怎么办" class="headerlink" title="自定义域名过期了怎么办"></a>自定义域名过期了怎么办</h3><p>如果曾经配置过<code>CNAME</code>,但是域名过期了,又没有新域名使用,你想使用<code>bla.github.io</code>来访问,但你会发现 github还是会跳转至你曾经的域名,解决办法是将 <code>CNAME</code>的内容更新为<code>bla.github.io</code></p>
</div>
<div>
</div>
<div>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2013/09/24/spring-aop-in-deep/" itemprop="url">
Spring AOP 实现原理
</a>
</h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">Posted on</span>
<time itemprop="dateCreated" datetime="2013-09-24T15:23:18+08:00" content="2013-09-24">
2013-09-24
</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h2 id="什么是AOP"><a href="#什么是AOP" class="headerlink" title="什么是AOP"></a>什么是AOP</h2><p>AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。</p>
<p>而AOP技术则恰恰相反,它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP代表的是一个横向的关系,如果说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向方面编程的方法,就仿佛一把利刃,将这些空心圆柱体剖开,以获得其内部的消息。而剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹。</p>
<p>使用“横切”技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。Aop 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。正如Avanade公司的高级方案构架师Adam Magee所说,AOP的核心思想就是“将应用程序中的商业逻辑同对其提供支持的通用服务进行分离。”</p>
<p>实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。</p>
<h2 id="AOP使用场景"><a href="#AOP使用场景" class="headerlink" title="AOP使用场景"></a>AOP使用场景</h2><p>AOP用来封装横切关注点,具体可以在下面的场景中使用:</p>
<ul>
<li>Authentication 权限</li>
<li>Caching 缓存</li>
<li>Context passing 内容传递</li>
<li>Error handling 错误处理</li>
<li>Lazy loading 懒加载</li>
<li>Debugging 调试</li>
<li>logging, tracing, profiling and monitoring 记录跟踪 优化 校准</li>
<li>Performance optimization 性能优化</li>
<li>Persistence 持久化</li>
<li>Resource pooling 资源池</li>
<li>Synchronization 同步</li>
<li>Transactions 事务</li>
</ul>
<h2 id="AOP相关概念"><a href="#AOP相关概念" class="headerlink" title="AOP相关概念"></a>AOP相关概念</h2><ul>
<li>方面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中一个很好的横切关注点例子。方面用Spring的 Advisor或拦截器实现。</li>
<li>连接点(Joinpoint): 程序执行过程中明确的点,如方法的调用或特定的异常被抛出。</li>
<li>通知(Advice): 在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。Spring中定义了四个advice: BeforeAdvice, AfterAdvice, ThrowAdvice和DynamicIntroductionAdvice</li>
<li>切入点(Pointcut): 指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点:例如,使用正则表达式。 Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解, MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上</li>
<li>引入(Introduction): 添加方法或字段到被通知的类。 Spring允许引入新的接口到任何被通知的对象。例如,你可以使用一个引入使任何对象实现 IsModified接口,来简化缓存。Spring中要使用Introduction, 可有通过DelegatingIntroductionInterceptor来实现通知,通过DefaultIntroductionAdvisor来配置Advice和代理类要实现的接口</li>
<li>目标对象(Target Object): 包含连接点的对象。也被称作被通知或被代理对象。POJO</li>
<li>AOP代理(AOP Proxy): AOP框架创建的对象,包含通知。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。</li>
<li>织入(Weaving): 组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。</li>
</ul>
<h2 id="Spring-AOP组件"><a href="#Spring-AOP组件" class="headerlink" title="Spring AOP组件"></a>Spring AOP组件</h2><p>下面这种类图列出了Spring中主要的AOP组件<br><img src="/images/spring-aop.jpg" alt=""></p>
<h2 id="如何使用Spring-AOP"><a href="#如何使用Spring-AOP" class="headerlink" title="如何使用Spring AOP"></a>如何使用Spring AOP</h2><p>可以通过配置文件或者编程的方式来使用Spring AOP。</p>
<p>配置可以通过xml文件来进行,大概有四种方式:</p>
<ol>
<li>配置ProxyFactoryBean,显式地设置advisors, advice, target等</li>
<li>配置AutoProxyCreator,这种方式下,还是如以前一样使用定义的bean,但是从容器中获得的其实已经是代理对象</li>
<li>通过<aop:config>来配置</aop:config></li>
<li>通过<aop: aspectj-autoproxy="">来配置,使用AspectJ的注解来标识通知及切入点</aop:></li>
</ol>
<p>也可以直接使用ProxyFactory来以编程的方式使用Spring AOP,通过ProxyFactory提供的方法可以设置target对象, advisor等相关配置,最终通过 getProxy()方法来获取代理对象</p>
<p>具体使用的示例可以google. 这里略去</p>
<h2 id="Spring-AOP代理对象的生成"><a href="#Spring-AOP代理对象的生成" class="headerlink" title="Spring AOP代理对象的生成"></a>Spring AOP代理对象的生成</h2><p>Spring提供了两种方式来生成代理对象: JDKProxy和Cglib,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。默认的策略是如果目标类是接口,则使用JDK动态代理技术,否则使用Cglib来生成代理。下面我们来研究一下Spring如何使用JDK来生成代理对象,具体的生成代码放在JdkDynamicAopProxy这个类中,直接上相关代码:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span><br><span class="line"> * <ol></span><br><span class="line"> * <li>获取代理类要实现的接口,除了Advised对象中配置的,还会加上SpringProxy, Advised(opaque=false)</span><br><span class="line"> * <li>检查上面得到的接口中有没有定义 equals或者hashcode的接口</span><br><span class="line"> * <li>调用Proxy.newProxyInstance创建代理对象</span><br><span class="line"> * </ol></span><br><span class="line"> */</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> Object <span class="title">getProxy</span><span class="params">(ClassLoader classLoader)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (logger.isDebugEnabled()) {</span><br><span class="line"> logger.debug(<span class="string">"Creating JDK dynamic proxy: target source is "</span> +<span class="keyword">this</span>.advised.getTargetSource());</span><br><span class="line"> }</span><br><span class="line"> Class[] proxiedInterfaces =AopProxyUtils.completeProxiedInterfaces(<span class="keyword">this</span>.advised);</span><br><span class="line"> findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);</span><br><span class="line"> <span class="keyword">return</span> Proxy.newProxyInstance(classLoader, proxiedInterfaces, <span class="keyword">this</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>那这个其实很明了,注释上我也已经写清楚了,不再赘述。</p>
<p>下面的问题是,代理对象生成了,那切面是如何织入的?<br>我们知道<code>InvocationHandler</code>是JDK动态代理的核心,生成的代理对象的方法调用都会委托到<code>InvocationHandler.invoke()</code>方法。而通过<code>JdkDynamicAopProxy</code>的签名我们可以看到这个类其实也实现了<code>InvocationHandler</code>,下面我们就通过分析这个类中实现的<code>invoke()</code>方法来具体看下Spring AOP是如何织入切面的。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">publicObject <span class="title">invoke</span><span class="params">(Object proxy, Method method, Object[] args)</span> throwsThrowable </span>{</span><br><span class="line"> MethodInvocation invocation = <span class="keyword">null</span>;</span><br><span class="line"> Object oldProxy = <span class="keyword">null</span>;</span><br><span class="line"> <span class="keyword">boolean</span> setProxyContext = <span class="keyword">false</span>;</span><br><span class="line"></span><br><span class="line"> TargetSource targetSource = <span class="keyword">this</span>.advised.targetSource;</span><br><span class="line"> Class targetClass = <span class="keyword">null</span>;</span><br><span class="line"> Object target = <span class="keyword">null</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="comment">//eqauls()方法,具目标对象未实现此方法</span></span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">this</span>.equalsDefined && AopUtils.isEqualsMethod(method)){</span><br><span class="line"> <span class="keyword">return</span> (equals(args[<span class="number">0</span>])? Boolean.TRUE : Boolean.FALSE);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//hashCode()方法,具目标对象未实现此方法</span></span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">this</span>.hashCodeDefined && AopUtils.isHashCodeMethod(method)){</span><br><span class="line"> <span class="keyword">return</span> newInteger(hashCode());</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//Advised接口或者其父接口中定义的方法,直接反射调用,不应用通知</span></span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">this</span>.advised.opaque &&method.getDeclaringClass().isInterface()</span><br><span class="line"> &&method.getDeclaringClass().isAssignableFrom(Advised.class)) {</span><br><span class="line"> <span class="comment">// Service invocations onProxyConfig with the proxy config...</span></span><br><span class="line"> <span class="keyword">return</span> AopUtils.invokeJoinpointUsingReflection(<span class="keyword">this</span>.advised,method, args);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> Object retVal = <span class="keyword">null</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">this</span>.advised.exposeProxy) {</span><br><span class="line"> <span class="comment">// Make invocation available ifnecessary.</span></span><br><span class="line"> oldProxy = AopContext.setCurrentProxy(proxy);</span><br><span class="line"> setProxyContext = <span class="keyword">true</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//获得目标对象的类</span></span><br><span class="line"> target = targetSource.getTarget();</span><br><span class="line"> <span class="keyword">if</span> (target != <span class="keyword">null</span>) {</span><br><span class="line"> targetClass = target.getClass();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//获取可以应用到此方法上的Interceptor列表</span></span><br><span class="line"> List chain = <span class="keyword">this</span>.advised.getInterceptorsAndDynamicInterceptionAdvice(method,targetClass);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//如果没有可以应用到此方法的通知(Interceptor),此直接反射调用 method.invoke(target, args)</span></span><br><span class="line"> <span class="keyword">if</span> (chain.isEmpty()) {</span><br><span class="line"> retVal = AopUtils.invokeJoinpointUsingReflection(target,method, args);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">//创建MethodInvocation</span></span><br><span class="line"> invocation = newReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);</span><br><span class="line"> retVal = invocation.proceed();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// Massage return value if necessary.</span></span><br><span class="line"> <span class="keyword">if</span> (retVal != <span class="keyword">null</span> && retVal == target &&method.getReturnType().isInstance(proxy)</span><br><span class="line"> &&!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {</span><br><span class="line"> <span class="comment">// Special case: it returned"this" and the return type of the method</span></span><br><span class="line"> <span class="comment">// is type-compatible. Notethat we can't help if the target sets</span></span><br><span class="line"> <span class="comment">// a reference to itself inanother returned object.</span></span><br><span class="line"> retVal = proxy;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> retVal;</span><br><span class="line"> } <span class="keyword">finally</span> {</span><br><span class="line"> <span class="keyword">if</span> (target != <span class="keyword">null</span> && !targetSource.isStatic()) {</span><br><span class="line"> <span class="comment">// Must have come fromTargetSource.</span></span><br><span class="line"> targetSource.releaseTarget(target);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (setProxyContext) {</span><br><span class="line"> <span class="comment">// Restore old proxy.</span></span><br><span class="line"> AopContext.setCurrentProxy(oldProxy);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br></pre></td></tr></table></figure>
<p>主流程可以简述为:获取可以应用到此方法上的通知链(Interceptor Chain),如果有,则应用通知,并执行joinpoint; 如果没有,则直接反射执行joinpoint。而这里的关键是通知链是如何获取的以及它又是如何执行的,下面逐一分析下。</p>
<p>首先,从上面的代码可以看到,通知链是通过<code>Advised.getInterceptorsAndDynamicInterceptionAdvice()</code>这个方法来获取的,我们来看下这个方法的实现:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> List<Object>getInterceptorsAndDynamicInterceptionAdvice(Method method, Class targetClass) {</span><br><span class="line"> MethodCacheKeycacheKey = <span class="keyword">new</span> MethodCacheKey(method);</span><br><span class="line"> List<Object>cached = <span class="keyword">this</span>.methodCache.get(cacheKey);</span><br><span class="line"> <span class="keyword">if</span>(cached == <span class="keyword">null</span>) {</span><br><span class="line"> cached= <span class="keyword">this</span>.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(</span><br><span class="line"> <span class="keyword">this</span>,method, targetClass);</span><br><span class="line"> <span class="keyword">this</span>.methodCache.put(cacheKey,cached);</span><br><span class="line"> }</span><br><span class="line"> returncached;</span><br><span class="line"> }</span><br></pre></td></tr></table></figure>
<p>可以看到实际的获取工作其实是由<code>AdvisorChainFactory. getInterceptorsAndDynamicInterceptionAdvice()</code>这个方法来完成的,获取到的结果会被缓存。<br>下面来分析下这个方法的实现:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span><br><span class="line"> * 从提供的配置实例config中获取advisor列表,遍历处理这些advisor.如果是IntroductionAdvisor,</span><br><span class="line"> * 则判断此Advisor能否应用到目标类targetClass上.如果是PointcutAdvisor,则判断</span><br><span class="line"> * 此Advisor能否应用到目标方法method上.将满足条件的Advisor通过AdvisorAdaptor转化成Interceptor列表返回.</span><br><span class="line"> */</span></span><br><span class="line"> <span class="function">publicList <span class="title">getInterceptorsAndDynamicInterceptionAdvice</span><span class="params">(Advised config, Methodmethod, Class targetClass)</span> </span>{</span><br><span class="line"> <span class="comment">// This is somewhat tricky... we have to process introductions first,</span></span><br><span class="line"> <span class="comment">// but we need to preserve order in the ultimate list.</span></span><br><span class="line"> List interceptorList = <span class="keyword">new</span> ArrayList(config.getAdvisors().length);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//查看是否包含IntroductionAdvisor</span></span><br><span class="line"> <span class="keyword">boolean</span> hasIntroductions = hasMatchingIntroductions(config,targetClass);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//这里实际上注册一系列AdvisorAdapter,用于将Advisor转化成MethodInterceptor</span></span><br><span class="line"> AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();</span><br><span class="line"></span><br><span class="line"> Advisor[] advisors = config.getAdvisors();</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i <advisors.length; i++) {</span><br><span class="line"> Advisor advisor = advisors[i];</span><br><span class="line"> <span class="keyword">if</span> (advisor <span class="keyword">instanceof</span> PointcutAdvisor) {</span><br><span class="line"> <span class="comment">// Add it conditionally.</span></span><br><span class="line"> PointcutAdvisor pointcutAdvisor= (PointcutAdvisor) advisor;</span><br><span class="line"> <span class="keyword">if</span>(config.isPreFiltered() ||pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) {</span><br><span class="line"> <span class="comment">//<span class="doctag">TODO:</span> 这个地方这两个方法的位置可以互换下</span></span><br><span class="line"> <span class="comment">//将Advisor转化成Interceptor</span></span><br><span class="line"> MethodInterceptor[]interceptors = registry.getInterceptors(advisor);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//检查当前advisor的pointcut是否可以匹配当前方法</span></span><br><span class="line"> MethodMatcher mm =pointcutAdvisor.getPointcut().getMethodMatcher();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (MethodMatchers.matches(mm,method, targetClass, hasIntroductions)) {</span><br><span class="line"> <span class="keyword">if</span>(mm.isRuntime()) {</span><br><span class="line"> <span class="comment">// Creating a newobject instance in the getInterceptors() method</span></span><br><span class="line"> <span class="comment">// isn't a problemas we normally cache created chains.</span></span><br><span class="line"> <span class="keyword">for</span> (intj = <span class="number">0</span>; j < interceptors.length; j++) {</span><br><span class="line"> interceptorList.add(<span class="keyword">new</span> InterceptorAndDynamicMethodMatcher(interceptors[j],mm));</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> interceptorList.addAll(Arrays.asList(interceptors));</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (advisor <span class="keyword">instanceof</span> IntroductionAdvisor){</span><br><span class="line"> IntroductionAdvisor ia =(IntroductionAdvisor) advisor;</span><br><span class="line"> <span class="keyword">if</span>(config.isPreFiltered() || ia.getClassFilter().matches(targetClass)) {</span><br><span class="line"> Interceptor[] interceptors= registry.getInterceptors(advisor);</span><br><span class="line"> interceptorList.addAll(Arrays.asList(interceptors));</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> Interceptor[] interceptors =registry.getInterceptors(advisor);</span><br><span class="line"> interceptorList.addAll(Arrays.asList(interceptors));</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> interceptorList;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>这个方法执行完成后,Advised中配置能够应用到连接点或者目标类的Advisor全部被转化成了MethodInterceptor.</p>
<p>接下来我们再看下得到的拦截器链是怎么起作用的。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (chain.isEmpty()) {</span><br><span class="line"> retVal = AopUtils.invokeJoinpointUsingReflection(target,method, args);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">//创建MethodInvocation</span></span><br><span class="line"> invocation = newReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);</span><br><span class="line"> retVal = invocation.proceed();</span><br><span class="line"> }</span><br></pre></td></tr></table></figure>
<p> 从这段代码可以看出,如果得到的拦截器链为空,则直接反射调用目标方法,否则创建MethodInvocation,调用其proceed方法,触发拦截器链的执行,来看下具体代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> Object <span class="title">proceed</span><span class="params">()</span> <span class="keyword">throws</span> Throwable </span>{</span><br><span class="line"> <span class="comment">// We start with an index of -1and increment early.</span></span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">this</span>.currentInterceptorIndex == <span class="keyword">this</span>.interceptorsAndDynamicMethodMatchers.size()- <span class="number">1</span>) {</span><br><span class="line"> <span class="comment">//如果Interceptor执行完了,则执行joinPoint</span></span><br><span class="line"> <span class="keyword">return</span> invokeJoinpoint();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> Object interceptorOrInterceptionAdvice =</span><br><span class="line"> <span class="keyword">this</span>.interceptorsAndDynamicMethodMatchers.get(++<span class="keyword">this</span>.currentInterceptorIndex);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//如果要动态匹配joinPoint</span></span><br><span class="line"> <span class="keyword">if</span> (interceptorOrInterceptionAdvice <span class="keyword">instanceof</span> InterceptorAndDynamicMethodMatcher){</span><br><span class="line"> <span class="comment">// Evaluate dynamic method matcher here: static part will already have</span></span><br><span class="line"> <span class="comment">// been evaluated and found to match.</span></span><br><span class="line"> InterceptorAndDynamicMethodMatcher dm =</span><br><span class="line"> (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;</span><br><span class="line"> <span class="comment">//动态匹配:运行时参数是否满足匹配条件</span></span><br><span class="line"> <span class="keyword">if</span> (dm.methodMatcher.matches(<span class="keyword">this</span>.method, <span class="keyword">this</span>.targetClass,<span class="keyword">this</span>.arguments)) {</span><br><span class="line"> <span class="comment">//执行当前Intercetpor</span></span><br><span class="line"> returndm.interceptor.invoke(<span class="keyword">this</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">//动态匹配失败时,略过当前Intercetpor,调用下一个Interceptor</span></span><br><span class="line"> <span class="keyword">return</span> proceed();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">// It's an interceptor, so we just invoke it: The pointcutwill have</span></span><br><span class="line"> <span class="comment">// been evaluated statically before this object was constructed.</span></span><br><span class="line"> <span class="comment">//执行当前Intercetpor</span></span><br><span class="line"> <span class="keyword">return</span> ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(<span class="keyword">this</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>代码也比较简单,这里不再赘述。</p>
</div>
<div>
</div>
<div>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2013/09/13/taste-jdk-proxy/" itemprop="url">
jdk动态代理实现原理
</a>
</h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">Posted on</span>
<time itemprop="dateCreated" datetime="2013-09-13T21:33:33+08:00" content="2013-09-13">
2013-09-13
</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<p>写在前面:</p>
<ul>
<li>大神和diao炸天的亲请绕道..</li>
<li>关于代理模式的概念这里省去,大家可以放鸟尽情搜..</li>
<li>关于为什么叫动态代理,个人理解是代理的类是在运行时动态生成的,大家也可以参考网上的理解..</li>
<li>文笔很差,所以文字较少,都在代码和注释中..</li>
</ul>
<p>=======一点不华丽的分割线————————-</p>
<p>开门见山,lets go..</p>
<p>java中可以通过jdk提供的 Proxy.newProxyInstance静态方法来创建动态代理对象,下面先来看看这个方法的实现</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Object <span class="title">newProxyInstance</span><span class="params">(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)</span></span><br><span class="line"> <span class="keyword">throws</span> IllegalArgumentException </span>{</span><br><span class="line"> <span class="comment">//InvocationHandler不能为空,因为对代理对象的所有方法调用实际上都会委托到InvocationHandler的invoke方法,</span></span><br><span class="line"> <span class="comment">//这个我们后面通过查看产生的代理类的源代码便会一目了然</span></span><br><span class="line"> <span class="keyword">if</span> (h == <span class="keyword">null</span>) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//这个是核心的地方,通过提供的ClassLoader和interface列表来产生代理类,具体的实现可以参考getProxyClass这个方法的实现,</span></span><br><span class="line"> <span class="comment">//真正的工作是由sun.misc.ProxyGenerator这个类来完成的,可以google查看具体的逻辑.在我们的程序中通过设置</span></span><br><span class="line"> <span class="comment">//System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true")可以查看产生的类文件</span></span><br><span class="line"> Class cl = getProxyClass(loader, interfaces);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//因为代理类继承了Proxy类.而Proxy中定义了构造函数protected Proxy(InvocationHandler h),所以可以反射得到Constructer实例</span></span><br><span class="line"> <span class="comment">//创建代理对象</span></span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> Constructor cons = cl.getConstructor(constructorParams);</span><br><span class="line"> <span class="keyword">return</span> (Object) cons.newInstance(<span class="keyword">new</span> Object[] { h });</span><br><span class="line"> } <span class="keyword">catch</span> (NoSuchMethodException e) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> InternalError(e.toString());</span><br><span class="line"> } <span class="keyword">catch</span> (IllegalAccessException e) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> InternalError(e.toString());</span><br><span class="line"> } <span class="keyword">catch</span> (InstantiationException e) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> InternalError(e.toString());</span><br><span class="line"> } <span class="keyword">catch</span> (InvocationTargetException e) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> InternalError(e.toString());</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>下面通过个例子来说明下:<br>先来定义一个接口,jdk的动态代理基于接口来创建代理类,不能基于类的原因是java不支持多重继承,而代理类都会继承Proxy类(个人理解).</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span><br><span class="line"> * Subject</span><br><span class="line"> *</span><br><span class="line"> * <span class="doctag">@author</span> Kevin Fan</span><br><span class="line"> * <span class="doctag">@since</span> 2013-9-13 下午2:43:33</span><br><span class="line"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Subject</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">void</span> <span class="title">pub</span><span class="params">(String key, String content)</span></span>;</span><br><span class="line"></span><br><span class="line"> <span class="function">String <span class="title">sub</span><span class="params">(String key)</span></span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>再来一个具体的实现,在代理模式中可以叫它的实例可以叫target,这个是真正执行操作的对象</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span><br><span class="line"> * SimpleSubject</span><br><span class="line"> *</span><br><span class="line"> * <span class="doctag">@author</span> Kevin Fan</span><br><span class="line"> * <span class="doctag">@since</span> 2013-9-13 下午2:45:03</span><br><span class="line"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SimpleSubject</span> <span class="keyword">implements</span> <span class="title">Subject</span> </span>{</span><br><span class="line"> <span class="keyword">private</span> Map<String, String> msg = <span class="keyword">new</span> ConcurrentHashMap<String, String>();</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">pub</span><span class="params">(String key, String content)</span> </span>{</span><br><span class="line"> System.out.println(<span class="string">"pub msg: key is "</span> + key + <span class="string">", content is "</span> + content);</span><br><span class="line"> msg.put(key, content);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">sub</span><span class="params">(String key)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (msg.containsKey(key)) {</span><br><span class="line"> String ret = msg.get(key);</span><br><span class="line"> System.out.println(<span class="string">"sub msg: key is "</span> + key + <span class="string">", result is "</span> + ret);</span><br><span class="line"> <span class="keyword">return</span> ret;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>好,接下来我们来写个动态代理工厂,根据 不同的target来创建动态代理对象</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span><br><span class="line"> * SubjectProxyFactory</span><br><span class="line"> *</span><br><span class="line"> * <span class="doctag">@author</span> Kevin Fan</span><br><span class="line"> * <span class="doctag">@since</span> 2013-9-13 下午2:47:24</span><br><span class="line"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SubjectProxyFactory</span> </span>{</span><br><span class="line"> <span class="comment">//<span class="doctag">TODO:</span> cache</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Subject <span class="title">getSubject</span><span class="params">(<span class="keyword">final</span> Subject realSubject)</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), <span class="keyword">new</span> Class[] { Subject.class },</span><br><span class="line"> <span class="keyword">new</span> InvocationHandler() {</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> Object <span class="title">invoke</span><span class="params">(Object proxy, Method method, Object[] args)</span> <span class="keyword">throws</span> Throwable </span>{</span><br><span class="line"> System.out.println(<span class="string">"\naction before method invocation...."</span>);</span><br><span class="line"> Object retVal = method.invoke(realSubject, args);</span><br><span class="line"> System.out.println(<span class="string">"action after method invocation....\n"</span>);</span><br><span class="line"> <span class="keyword">return</span> retVal;</span><br><span class="line"> }</span><br><span class="line"> });</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>可以看到这是一个简单的实现,只是在真实对象执行前后各打一句信息..</p>
<p>接下来用一个 main函数来把这些结合起来</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span><br><span class="line"> * Demo</span><br><span class="line"> *</span><br><span class="line"> * <span class="doctag">@author</span> Kevin Fan</span><br><span class="line"> * <span class="doctag">@since</span> 2013-9-13 下午2:50:28</span><br><span class="line"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>{</span><br><span class="line"> <span class="comment">//设置此系统属性,以查看代理类文件</span></span><br><span class="line"> System.setProperty(<span class="string">"sun.misc.ProxyGenerator.saveGeneratedFiles"</span>, <span class="string">"true"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//创建真实对象</span></span><br><span class="line"> Subject subj = <span class="keyword">new</span> SimpleSubject();</span><br><span class="line"> subj.pub(<span class="string">"name"</span>, <span class="string">"kevin.fan"</span>);</span><br><span class="line"> subj.sub(<span class="string">"name"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//创建代理对象</span></span><br><span class="line"> Subject proxy = SubjectProxyFactory.getSubject(subj);</span><br><span class="line"> proxy.pub(<span class="string">"hobby"</span>, <span class="string">"r&b music"</span>);</span><br><span class="line"> proxy.sub(<span class="string">"name"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>ok,小手抖一下,走你,看下执行结果</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">pub msg: key is name, content is kevin.fan</span><br><span class="line">sub msg: key is name, result is kevin.fan</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">action before method invocation....</span><br><span class="line">pub msg: key is hobby, content is r&b music</span><br><span class="line">action after method invocation....</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">action before method invocation....</span><br><span class="line">sub msg: key is name, result is kevin.fan</span><br><span class="line">action after method invocation....</span><br></pre></td></tr></table></figure>
<p>可以看到在调用代理对象的方法时,添加的额外动作已经生效,接下来我们看下生成的代理类的代码..</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> com.aliyun.demo.kevin.coder.lang.proxy.Subject;</span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.InvocationHandler;</span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.Method;</span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.Proxy;</span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.UndeclaredThrowableException;</span><br><span class="line"></span><br><span class="line"><span class="comment">//这里很清楚了,代理类继承了Proxy类,并且实现了Proxy.newProxyInstance这个方法中传入的接口</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> $<span class="title">Proxy0</span> <span class="keyword">extends</span> <span class="title">Proxy</span></span><br><span class="line"><span class="keyword">implements</span> <span class="title">Subject</span></span><br><span class="line"></span>{</span><br><span class="line"></span><br><span class="line"> <span class="comment">//这些方法在下面的static init block中进行初始化</span></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> Method m4;</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> Method m1;</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> Method m3;</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> Method m0;</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> Method m2;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">static</span></span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">try</span></span><br><span class="line"> {</span><br><span class="line"> m4 = Class.forName(<span class="string">"com.aliyun.demo.kevin.coder.lang.proxy.Subject"</span>).getMethod(<span class="string">"sub"</span>, <span class="keyword">new</span> Class[] { Class.forName(<span class="string">"java.lang.String"</span>) });</span><br><span class="line"> m1 = Class.forName(<span class="string">"java.lang.Object"</span>).getMethod(<span class="string">"equals"</span>, <span class="keyword">new</span> Class[] { Class.forName(<span class="string">"java.lang.Object"</span>) });</span><br><span class="line"> m3 = Class.forName(<span class="string">"com.aliyun.demo.kevin.coder.lang.proxy.Subject"</span>).getMethod(<span class="string">"pub"</span>, <span class="keyword">new</span> Class[] { Class.forName(<span class="string">"java.lang.String"</span>), Class.forName(<span class="string">"java.lang.String"</span>) });</span><br><span class="line"> m0 = Class.forName(<span class="string">"java.lang.Object"</span>).getMethod(<span class="string">"hashCode"</span>, <span class="keyword">new</span> Class[<span class="number">0</span>]);</span><br><span class="line"> m2 = Class.forName(<span class="string">"java.lang.Object"</span>).getMethod(<span class="string">"toString"</span>, <span class="keyword">new</span> Class[<span class="number">0</span>]);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">catch</span> (NoSuchMethodException localNoSuchMethodException)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> NoSuchMethodError(localNoSuchMethodException.getMessage());</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">catch</span> (ClassNotFoundException localClassNotFoundException)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> NoClassDefFoundError(localClassNotFoundException.getMessage());</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//构造函数,接收一个 InvocationHandler作为参数,这就是为什么Proxy.newProxyInstance方法里可以</span></span><br><span class="line"> <span class="comment">//通过InvocationHandler实例作为参数来反射获取Constructer实例</span></span><br><span class="line"> <span class="keyword">public</span> $Proxy0 paramInvocationHandler)</span><br><span class="line"> <span class="keyword">throws</span></span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">super</span>(paramInvocationHandler);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//下面通过这个来看下代理对象中方法是怎样调用的</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> String <span class="title">sub</span><span class="params">(String paramString)</span></span><br><span class="line"> <span class="keyword">throws</span></span><br><span class="line"> </span>{</span><br><span class="line"> <span class="keyword">try</span></span><br><span class="line"> {</span><br><span class="line"> <span class="comment">//全部是通过调用InvocationHandler的invoke方法,传入对应的方法和参数</span></span><br><span class="line"> <span class="keyword">return</span> (String)<span class="keyword">this</span>.h.invoke(<span class="keyword">this</span>, m4, <span class="keyword">new</span> Object[] { paramString });</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">catch</span> (Error|RuntimeException localError)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">throw</span> localError;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">catch</span> (Throwable localThrowable)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> UndeclaredThrowableException(localThrowable);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">boolean</span> <span class="title">equals</span><span class="params">(Object paramObject)</span></span><br><span class="line"> <span class="keyword">throws</span></span><br><span class="line"> </span>{</span><br><span class="line"> <span class="keyword">try</span></span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">return</span> ((Boolean)<span class="keyword">this</span>.h.invoke(<span class="keyword">this</span>, m1, <span class="keyword">new</span> Object[] { paramObject })).booleanValue();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">catch</span> (Error|RuntimeException localError)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">throw</span> localError;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">catch</span> (Throwable localThrowable)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> UndeclaredThrowableException(localThrowable);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title">pub</span><span class="params">(String paramString1, String paramString2)</span></span><br><span class="line"> <span class="keyword">throws</span></span><br><span class="line"> </span>{</span><br><span class="line"> <span class="keyword">try</span></span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">this</span>.h.invoke(<span class="keyword">this</span>, m3, <span class="keyword">new</span> Object[] { paramString1, paramString2 });</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">catch</span> (Error|RuntimeException localError)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">throw</span> localError;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">catch</span> (Throwable localThrowable)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> UndeclaredThrowableException(localThrowable);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">int</span> <span class="title">hashCode</span><span class="params">()</span></span><br><span class="line"> <span class="keyword">throws</span></span><br><span class="line"> </span>{</span><br><span class="line"> <span class="keyword">try</span></span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">return</span> ((Integer)<span class="keyword">this</span>.h.invoke(<span class="keyword">this</span>, m0, <span class="keyword">null</span>)).intValue();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">catch</span> (Error|RuntimeException localError)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">throw</span> localError;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">catch</span> (Throwable localThrowable)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> UndeclaredThrowableException(localThrowable);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> String <span class="title">toString</span><span class="params">()</span></span><br><span class="line"> <span class="keyword">throws</span></span><br><span class="line"> </span>{</span><br><span class="line"> <span class="keyword">try</span></span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">return</span> (String)<span class="keyword">this</span>.h.invoke(<span class="keyword">this</span>, m2, <span class="keyword">null</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">catch</span> (Error|RuntimeException localError)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">throw</span> localError;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">catch</span> (Throwable localThrowable)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> UndeclaredThrowableException(localThrowable);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
</div>
<div>
</div>
<div>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2012/11/29/junit-test-java-io-speed/" itemprop="url">
Java IO读取速度测试
</a>
</h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">Posted on</span>
<time itemprop="dateCreated" datetime="2012-11-29T23:43:39+08:00" content="2012-11-29">
2012-11-29
</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<p>不知道是什么情况,今天喜欢上了看IO这个东东。。回来码了几行简单的不能再简单的代码 ,跑了一把,得了几个 数据 ,放到这里跟大家分享下。。<br>先把测试的结果截图摆上来欣赏一下:有一点需要说明的是,前四个方法是以字节流的形式读取一个大小为11M左右的rar文件,后面两个 方法是以字符流的形式读取在小在1M~2M之间的一个文本文件~</p>
<p><img src="/images/java-io-speed.jpg" alt=""></p>
<p>具体每个方法是怎么实现 的,代码简单到了什么程度,常用到了什么程度 。。。。。。<br>话不多说,元芳,代码在这里,你怎么看?</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">IOSpeedTest</span> </span>{</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> String file = <span class="string">"G:\\pt.rar"</span>;</span><br><span class="line"></span><br><span class="line"> <span class="annotation">@Test</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testWithoutBuf</span><span class="params">()</span> <span class="keyword">throws</span> IOException </span>{</span><br><span class="line"> <span class="keyword">int</span> line = <span class="number">0</span>;</span><br><span class="line"> FileInputStream in = <span class="keyword">new</span> FileInputStream(file);</span><br><span class="line"> <span class="keyword">int</span> bit = -<span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span> ((bit = in.read()) != -<span class="number">1</span>) {</span><br><span class="line"> <span class="keyword">if</span> (bit == <span class="string">'\n'</span>) {</span><br><span class="line"> ++line;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (in != <span class="keyword">null</span>) {</span><br><span class="line"> in.close();</span><br><span class="line"> }</span><br><span class="line"> System.out.println(line);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="annotation">@Test</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testWithBufferedIn</span><span class="params">()</span> <span class="keyword">throws</span> IOException </span>{</span><br><span class="line"> BufferedInputStream in = <span class="keyword">new</span> BufferedInputStream(<span class="keyword">new</span> FileInputStream(file));</span><br><span class="line"> <span class="keyword">int</span> line = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">int</span> bit = -<span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span> ((bit = in.read()) != -<span class="number">1</span>) {</span><br><span class="line"> <span class="keyword">if</span> (bit == <span class="string">'\n'</span>) {</span><br><span class="line"> ++line;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (in != <span class="keyword">null</span>) {</span><br><span class="line"> in.close();</span><br><span class="line"> }</span><br><span class="line"> System.out.println(line);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="annotation">@Test</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testWithFixedBuf</span><span class="params">()</span> <span class="keyword">throws</span> IOException </span>{</span><br><span class="line"> <span class="keyword">int</span> bufSize = <span class="number">8196</span>;</span><br><span class="line"> FileInputStream in = <span class="keyword">new</span> FileInputStream(file);</span><br><span class="line"> <span class="keyword">int</span> line = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">byte</span>[] buf = <span class="keyword">new</span> <span class="keyword">byte</span>[bufSize];</span><br><span class="line"> <span class="keyword">while</span> (in.read(buf) != -<span class="number">1</span>) {</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">byte</span> element : buf) {</span><br><span class="line"> <span class="keyword">if</span> (element == <span class="string">'\n'</span>) {</span><br><span class="line"> ++line;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (in != <span class="keyword">null</span>) {</span><br><span class="line"> in.close();</span><br><span class="line"> }</span><br><span class="line"> System.out.println(line);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="annotation">@Test</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testWithWholeFile</span><span class="params">()</span> <span class="keyword">throws</span> IOException </span>{</span><br><span class="line"> FileInputStream in = <span class="keyword">new</span> FileInputStream(file);</span><br><span class="line"> <span class="keyword">int</span> line = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">byte</span>[] buf = <span class="keyword">new</span> <span class="keyword">byte</span>[file.length()];</span><br><span class="line"> in.read(buf);</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">byte</span> element : buf) {</span><br><span class="line"> <span class="keyword">if</span> (element == <span class="string">'\n'</span>) {</span><br><span class="line"> ++line;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (in != <span class="keyword">null</span>) {</span><br><span class="line"> in.close();</span><br><span class="line"> }</span><br><span class="line"> System.out.println(line);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> String txt = <span class="string">"G:\\cy.txt"</span>;</span><br><span class="line"></span><br><span class="line"> <span class="annotation">@Test</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testWithBf</span><span class="params">()</span> <span class="keyword">throws</span> IOException </span>{</span><br><span class="line"> BufferedReader bf = <span class="keyword">new</span> BufferedReader(<span class="keyword">new</span> InputStreamReader(<span class="keyword">new</span> FileInputStream(txt)));</span><br><span class="line"> <span class="keyword">while</span> (bf.readLine() != <span class="keyword">null</span>) {</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="annotation">@Test</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testWithFixedBf</span><span class="params">()</span> <span class="keyword">throws</span> IOException </span>{</span><br><span class="line"> <span class="keyword">int</span> bufSize = <span class="number">8196</span>;</span><br><span class="line"> InputStreamReader reader = <span class="keyword">new</span> InputStreamReader(<span class="keyword">new</span> FileInputStream(txt));</span><br><span class="line"> <span class="keyword">char</span>[] buf = <span class="keyword">new</span> <span class="keyword">char</span>[bufSize];</span><br><span class="line"> <span class="keyword">while</span> (reader.read(buf) != -<span class="number">1</span>) {</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> reader.close();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>好长时间没有自己写过文章了,今天写这么水的东西出来,求轻喷。。~~<br>kevin 11/29/2012</p>
</div>
<div>
</div>
<div>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
</section>
</div>
</div>
<div class="sidebar-toggle">
<div class="sidebar-toggle-line-wrap">
<span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
<span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
<span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
</div>
</div>
<aside id="sidebar" class="sidebar">
<div class="sidebar-inner">