1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 org.apache.lucene.codecs.lucene40.Lucene40Codec
17 org.apache.lucene.codecs.lucene3x.Lucene3xCodec
18 org.apache.lucene.codecs.lucene41.Lucene41Codec
19 org.apache.lucene.codecs.lucene42.Lucene42Codec
20 org.apache.lucene.codecs.lucene45.Lucene45Codec
21 org.apache.lucene.codecs.lucene46.Lucene46Codec
接下来可以看下Codec服务接口的实现代码
1 package org.apache.lucene.codecs;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with
6 * this work for additional information regarding copyright ownership.
7 * The ASF licenses this file to You under the Apache License, Version 2.0
8 * (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 import java.util.Set;
21 import java.util.ServiceLoader; // javadocs
22
23 import org.apache.lucene.index.IndexWriterConfig; // javadocs
24 import org.apache.lucene.util.NamedSPILoader;
25
26 /**
27 * Encodes/decodes an inverted index segment.
28 *
29 * Note, when extending this class, the name ({@link #getName}) is
30 * written into the index. In order for the segment to be read, the
31 * name must resolve to your implementation via {@link #forName(String)}.
32 * This method uses Java's
33 * {@link ServiceLoader Service Provider Interface} (SPI) to resolve codec names.
34 *
35 * If you implement your own codec, make sure that it has a no-arg constructor
36 * so SPI can load it.
37 * @see ServiceLoader
38 */
39 public abstract class Codec implements NamedSPILoader.NamedSPI {
40
41 private static final NamedSPILoader loader =
42 new NamedSPILoader(Codec.class);
43
44 private final String name;
45
46 /**
47 * Creates a new codec.
48 *
49 * The provided name will be written into the index segment: in order to
50 * for the segment to be read this class should be registered with Java's
51 * SPI mechanism (registered in META-INF/ of your jar file, etc).
52 * @param name must be all ascii alphanumeric, and less than 128 characters in length.
53 */
54 protected Codec(String name) {
55 NamedSPILoader.checkServiceName(name);
56 this.name = name;
57 }
58
59 /** Returns this codec's name */
60 @Override
61 public final String getName() {
62 return name;
63 }
64 /**
65 * 以下几个Format跟Lucene的索引文件格式有关
66 * */
67 /** Encodes/decodes postings */
68 public abstract PostingsFormat postingsFormat();
69
70 /** Encodes/decodes docvalues */
71 public abstract DocValuesFormat docValuesFormat();
72
73 /** Encodes/decodes stored fields */
74 public abstract StoredFieldsFormat storedFieldsFormat();
75
76 /** Encodes/decodes term vectors */
77 public abstract TermVectorsFormat termVectorsFormat();
78
79 /** Encodes/decodes field infos file */
80 public abstract FieldInfosFormat fieldInfosFormat();
81
82 /** Encodes/decodes segment info file */
83 public abstract SegmentInfoFormat segmentInfoFormat();
84
85 /** Encodes/decodes document normalization values */
86 public abstract NormsFormat normsFormat();
87
88 /** Encodes/decodes live docs */
89 public abstract LiveDocsFormat liveDocsFormat();
90
91 /**
92 * 根据名字在已有的Codec实例中寻找符合
93 * */
94 /** looks up a codec by name */
95 public static Codec forName(String name) {
96 if (loader == null) {
97 throw new IllegalStateException("You called Codec.forName() before all Codecs could be initialized. "+
98 "This likely happens if you call it from a Codec's ctor.");
99 }
100 return loader.lookup(name);
101 }
102
103 /**
104 * 返回有效的Codecs实例
105 * */
106 /** returns a list of all available codec names */
107 public static Set availableCodecs() {
108 if (loader == null) {
109 throw new IllegalStateException("You called Codec.availableCodecs() before all Codecs could be initialized. "+
110 "This likely happens if you call it from a Codec's ctor.");
111 }
112 return loader.availableServices();
113 }
114
115 /**
116 * 更新Codec实例列表,Codec实例列表只能添加,不能删除与更改。
117 * */
118 /**
119 * Reloads the codec list from the given {@link ClassLoader}.
120 * Changes to the codecs are visible after the method ends, all
121 * iterators ({@link #availableCodecs()},...) stay consistent.
122 *
123 * NOTE: Only new codecs are added, existing ones are
124 * never removed or replaced.
125 *
126 * This method is expensive and should only be called for discovery
127 * of new codecs on the given classpath/classloader!
128 */
129 public static void reloadCodecs(ClassLoader classloader) {
130 loader.reload(classloader);
131 }
132
133 /**
134 * 默认为Lucene46,也就是说默认调用的是org.apache.lucene.codecs.lucene46.Lucene46Codec
135 * */
136 private static Codec defaultCodec = Codec.forName("Lucene46");
137
138 /**
139 * 返回默认的Codec实例
140 * */
141 /** expert: returns the default codec used for newly created
142 * {@link IndexWriterConfig}s.
143 */
144 // TODO: should we use this, or maybe a system property is better?
145 public static Codec getDefault() {
146 return defaultCodec;
147 }
148
149 /**
150 * 设置默认的Codec实例
151 * */
152 /** expert: sets the default codec used for newly created
153 * {@link IndexWriterConfig}s.
154 */
155 public static void setDefault(Codec codec) {
156 defaultCodec = codec;
157 }
158
159 /**
160 * returns the codec's name. Subclasses can override to provide
161 * more detail (such as parameters).
162 */
163 @Override
164 public String toString() {
165 return name;
166 }
167 }
代码比较简单明了,接下来再看下NamedSPILoader.NamedSPI,它封装了JAVA SPI的实现:
1 package org.apache.lucene.util;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with
6 * this work for additional information regarding copyright ownership.
7 * The ASF licenses this file to You under the Apache License, Version 2.0
8 * (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 import java.util.Collections;
21 import java.util.Iterator;
22 import java.util.Map;
23 import java.util.LinkedHashMap;
24 import java.util.Set;
25 import java.util.ServiceConfigurationError;
26
27 /**
28 * Helper class for loading named SPIs from classpath (e.g. Codec, PostingsFormat).
29 * @lucene.internal
30 */
31 public final class NamedSPILoader implements Iterable {
32
33 /**
34 * SPI service Map,存放服务对应的实例类。
35 * */
36 private volatile Map services = Collections.emptyMap();
37 private final Class clazz;
38
39 public NamedSPILoader(Class clazz) {
40 this(clazz, Thread.currentThread().getContextClassLoader());
41 }
42
43 public NamedSPILoader(Class clazz, ClassLoader classloader) {
44 this.clazz = clazz;
45 // if clazz' classloader is not a parent of the given one, we scan clazz's classloader, too:
46 final ClassLoader clazzClassloader = clazz.getClassLoader();
47 if (clazzClassloader != null && !SPIClassIterator.isParentClassLoader(clazzClassloader, classloader)) {
48 reload(clazzClassloader);
49 }
50 reload(classloader);
51 }
52
53 /**
54 * 更新SPI MAP services。遍历META-INF/services文件,如果services MAP没有该实例,则新建实例,并放入services MAP
55 * */
56 /**
57 * Reloads the internal SPI list from the given {@link ClassLoader}.
58 * Changes to the service list are visible after the method ends, all
59 * iterators ({@link #iterator()},...) stay consistent.
60 *
61 * NOTE: Only new service providers are added, existing ones are
62 * never removed or replaced.
63 *
64 * This method is expensive and should only be called for discovery
65 * of new service providers on the given classpath/classloader!
66 */
67 public synchronized void reload(ClassLoader classloader) {
68 final LinkedHashMap services = new LinkedHashMap(this.services);
69 final SPIClassIterator loader = SPIClassIterator.get(clazz, classloader);
70 while (loader.hasNext()) {
71 final Class