1*3ff81872SXin Li<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 2*3ff81872SXin Li<!--NewPage--> 3*3ff81872SXin Li<HTML> 4*3ff81872SXin Li<HEAD> 5*3ff81872SXin Li<!-- Generated by javadoc (build 1.5.0_16) on Mon Oct 12 16:11:20 PDT 2009 --> 6*3ff81872SXin Li<TITLE> 7*3ff81872SXin Lijavax.inject 8*3ff81872SXin Li</TITLE> 9*3ff81872SXin Li 10*3ff81872SXin Li<META NAME="keywords" CONTENT="javax.inject package"> 11*3ff81872SXin Li 12*3ff81872SXin Li<LINK REL ="stylesheet" TYPE="text/css" HREF="../../stylesheet.css" TITLE="Style"> 13*3ff81872SXin Li 14*3ff81872SXin Li<SCRIPT type="text/javascript"> 15*3ff81872SXin Lifunction windowTitle() 16*3ff81872SXin Li{ 17*3ff81872SXin Li parent.document.title="javax.inject"; 18*3ff81872SXin Li} 19*3ff81872SXin Li</SCRIPT> 20*3ff81872SXin Li<NOSCRIPT> 21*3ff81872SXin Li</NOSCRIPT> 22*3ff81872SXin Li 23*3ff81872SXin Li</HEAD> 24*3ff81872SXin Li 25*3ff81872SXin Li<BODY BGCOLOR="white" onload="windowTitle();"> 26*3ff81872SXin Li 27*3ff81872SXin Li 28*3ff81872SXin Li<!-- ========= START OF TOP NAVBAR ======= --> 29*3ff81872SXin Li<A NAME="navbar_top"><!-- --></A> 30*3ff81872SXin Li<A HREF="#skip-navbar_top" title="Skip navigation links"></A> 31*3ff81872SXin Li<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY=""> 32*3ff81872SXin Li<TR> 33*3ff81872SXin Li<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> 34*3ff81872SXin Li<A NAME="navbar_top_firstrow"><!-- --></A> 35*3ff81872SXin Li<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY=""> 36*3ff81872SXin Li <TR ALIGN="center" VALIGN="top"> 37*3ff81872SXin Li <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../javax/inject/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A> </TD> 38*3ff81872SXin Li <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT> </TD> 39*3ff81872SXin Li <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A> </TD> 40*3ff81872SXin Li <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A> </TD> 41*3ff81872SXin Li <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A> </TD> 42*3ff81872SXin Li <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A> </TD> 43*3ff81872SXin Li </TR> 44*3ff81872SXin Li</TABLE> 45*3ff81872SXin Li</TD> 46*3ff81872SXin Li<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM> 47*3ff81872SXin Li</EM> 48*3ff81872SXin Li</TD> 49*3ff81872SXin Li</TR> 50*3ff81872SXin Li 51*3ff81872SXin Li<TR> 52*3ff81872SXin Li<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2"> 53*3ff81872SXin Li PREV PACKAGE 54*3ff81872SXin Li NEXT PACKAGE</FONT></TD> 55*3ff81872SXin Li<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2"> 56*3ff81872SXin Li <A HREF="../../index.html?javax/inject/package-summary.html" target="_top"><B>FRAMES</B></A> 57*3ff81872SXin Li <A HREF="package-summary.html" target="_top"><B>NO FRAMES</B></A> 58*3ff81872SXin Li <SCRIPT type="text/javascript"> 59*3ff81872SXin Li <!-- 60*3ff81872SXin Li if(window==top) { 61*3ff81872SXin Li document.writeln('<A HREF="../../allclasses-noframe.html"><B>All Classes</B></A>'); 62*3ff81872SXin Li } 63*3ff81872SXin Li //--> 64*3ff81872SXin Li</SCRIPT> 65*3ff81872SXin Li<NOSCRIPT> 66*3ff81872SXin Li <A HREF="../../allclasses-noframe.html"><B>All Classes</B></A> 67*3ff81872SXin Li</NOSCRIPT> 68*3ff81872SXin Li 69*3ff81872SXin Li 70*3ff81872SXin Li</FONT></TD> 71*3ff81872SXin Li</TR> 72*3ff81872SXin Li</TABLE> 73*3ff81872SXin Li<A NAME="skip-navbar_top"></A> 74*3ff81872SXin Li<!-- ========= END OF TOP NAVBAR ========= --> 75*3ff81872SXin Li 76*3ff81872SXin Li<HR> 77*3ff81872SXin Li<H2> 78*3ff81872SXin LiPackage javax.inject 79*3ff81872SXin Li</H2> 80*3ff81872SXin LiThis package specifies a means for obtaining objects in such a way as to 81*3ff81872SXin Li maximize reusability, testability and maintainability compared to 82*3ff81872SXin Li traditional approaches such as constructors, factories, and service 83*3ff81872SXin Li locators (e.g., JNDI). This process, known as <i>dependency 84*3ff81872SXin Li injection</i>, is beneficial to most nontrivial applications. 85*3ff81872SXin Li<P> 86*3ff81872SXin Li<B>See:</B> 87*3ff81872SXin Li<BR> 88*3ff81872SXin Li <A HREF="#package_description"><B>Description</B></A> 89*3ff81872SXin Li<P> 90*3ff81872SXin Li 91*3ff81872SXin Li<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY=""> 92*3ff81872SXin Li<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> 93*3ff81872SXin Li<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2"> 94*3ff81872SXin Li<B>Interface Summary</B></FONT></TH> 95*3ff81872SXin Li</TR> 96*3ff81872SXin Li<TR BGCOLOR="white" CLASS="TableRowColor"> 97*3ff81872SXin Li<TD WIDTH="15%"><B><A HREF="../../javax/inject/Provider.html" title="interface in javax.inject">Provider<T></A></B></TD> 98*3ff81872SXin Li<TD>Provides instances of <code>T</code>.</TD> 99*3ff81872SXin Li</TR> 100*3ff81872SXin Li</TABLE> 101*3ff81872SXin Li 102*3ff81872SXin Li 103*3ff81872SXin Li<P> 104*3ff81872SXin Li 105*3ff81872SXin Li<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY=""> 106*3ff81872SXin Li<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> 107*3ff81872SXin Li<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2"> 108*3ff81872SXin Li<B>Annotation Types Summary</B></FONT></TH> 109*3ff81872SXin Li</TR> 110*3ff81872SXin Li<TR BGCOLOR="white" CLASS="TableRowColor"> 111*3ff81872SXin Li<TD WIDTH="15%"><B><A HREF="../../javax/inject/Inject.html" title="annotation in javax.inject">Inject</A></B></TD> 112*3ff81872SXin Li<TD>Identifies injectable constructors, methods, and fields.</TD> 113*3ff81872SXin Li</TR> 114*3ff81872SXin Li<TR BGCOLOR="white" CLASS="TableRowColor"> 115*3ff81872SXin Li<TD WIDTH="15%"><B><A HREF="../../javax/inject/Named.html" title="annotation in javax.inject">Named</A></B></TD> 116*3ff81872SXin Li<TD>String-based <A HREF="../../javax/inject/Qualifier.html" title="annotation in javax.inject">qualifier</A>.</TD> 117*3ff81872SXin Li</TR> 118*3ff81872SXin Li<TR BGCOLOR="white" CLASS="TableRowColor"> 119*3ff81872SXin Li<TD WIDTH="15%"><B><A HREF="../../javax/inject/Qualifier.html" title="annotation in javax.inject">Qualifier</A></B></TD> 120*3ff81872SXin Li<TD>Identifies qualifier annotations.</TD> 121*3ff81872SXin Li</TR> 122*3ff81872SXin Li<TR BGCOLOR="white" CLASS="TableRowColor"> 123*3ff81872SXin Li<TD WIDTH="15%"><B><A HREF="../../javax/inject/Scope.html" title="annotation in javax.inject">Scope</A></B></TD> 124*3ff81872SXin Li<TD>Identifies scope annotations.</TD> 125*3ff81872SXin Li</TR> 126*3ff81872SXin Li<TR BGCOLOR="white" CLASS="TableRowColor"> 127*3ff81872SXin Li<TD WIDTH="15%"><B><A HREF="../../javax/inject/Singleton.html" title="annotation in javax.inject">Singleton</A></B></TD> 128*3ff81872SXin Li<TD>Identifies a type that the injector only instantiates once.</TD> 129*3ff81872SXin Li</TR> 130*3ff81872SXin Li</TABLE> 131*3ff81872SXin Li 132*3ff81872SXin Li 133*3ff81872SXin Li<P> 134*3ff81872SXin Li<A NAME="package_description"><!-- --></A><H2> 135*3ff81872SXin LiPackage javax.inject Description 136*3ff81872SXin Li</H2> 137*3ff81872SXin Li 138*3ff81872SXin Li<P> 139*3ff81872SXin LiThis package specifies a means for obtaining objects in such a way as to 140*3ff81872SXin Li maximize reusability, testability and maintainability compared to 141*3ff81872SXin Li traditional approaches such as constructors, factories, and service 142*3ff81872SXin Li locators (e.g., JNDI). This process, known as <i>dependency 143*3ff81872SXin Li injection</i>, is beneficial to most nontrivial applications. 144*3ff81872SXin Li 145*3ff81872SXin Li <p>Many types depend on other types. For example, a <tt>Stopwatch</tt> might 146*3ff81872SXin Li depend on a <tt>TimeSource</tt>. The types on which a type depends are 147*3ff81872SXin Li known as its <i>dependencies</i>. The process of finding an instance of a 148*3ff81872SXin Li dependency to use at run time is known as <i>resolving</i> the dependency. 149*3ff81872SXin Li If no such instance can be found, the dependency is said to be 150*3ff81872SXin Li <i>unsatisfied</i>, and the application is broken. 151*3ff81872SXin Li 152*3ff81872SXin Li <p>In the absence of dependency injection, an object can resolve its 153*3ff81872SXin Li dependencies in a few ways. It can invoke a constructor, hard-wiring an 154*3ff81872SXin Li object directly to its dependency's implementation and life cycle: 155*3ff81872SXin Li 156*3ff81872SXin Li <pre> class Stopwatch { 157*3ff81872SXin Li final TimeSource timeSource; 158*3ff81872SXin Li Stopwatch () { 159*3ff81872SXin Li timeSource = <b>new AtomicClock(...)</b>; 160*3ff81872SXin Li } 161*3ff81872SXin Li void start() { ... } 162*3ff81872SXin Li long stop() { ... } 163*3ff81872SXin Li }</pre> 164*3ff81872SXin Li 165*3ff81872SXin Li <p>If more flexibility is needed, the object can call out to a factory or 166*3ff81872SXin Li service locator: 167*3ff81872SXin Li 168*3ff81872SXin Li <pre> class Stopwatch { 169*3ff81872SXin Li final TimeSource timeSource; 170*3ff81872SXin Li Stopwatch () { 171*3ff81872SXin Li timeSource = <b>DefaultTimeSource.getInstance()</b>; 172*3ff81872SXin Li } 173*3ff81872SXin Li void start() { ... } 174*3ff81872SXin Li long stop() { ... } 175*3ff81872SXin Li }</pre> 176*3ff81872SXin Li 177*3ff81872SXin Li <p>In deciding between these traditional approaches to dependency 178*3ff81872SXin Li resolution, a programmer must make trade-offs. Constructors are more 179*3ff81872SXin Li concise but restrictive. Factories decouple the client and implementation 180*3ff81872SXin Li to some extent but require boilerplate code. Service locators decouple even 181*3ff81872SXin Li further but reduce compile time type safety. All three approaches inhibit 182*3ff81872SXin Li unit testing. For example, if the programmer uses a factory, each test 183*3ff81872SXin Li against code that depends on the factory will have to mock out the factory 184*3ff81872SXin Li and remember to clean up after itself or else risk side effects: 185*3ff81872SXin Li 186*3ff81872SXin Li <pre> void testStopwatch() { 187*3ff81872SXin Li <b>TimeSource original = DefaultTimeSource.getInstance(); 188*3ff81872SXin Li DefaultTimeSource.setInstance(new MockTimeSource()); 189*3ff81872SXin Li try {</b> 190*3ff81872SXin Li // Now, we can actually test Stopwatch. 191*3ff81872SXin Li Stopwatch sw = new Stopwatch(); 192*3ff81872SXin Li ... 193*3ff81872SXin Li <b>} finally { 194*3ff81872SXin Li DefaultTimeSource.setInstance(original); 195*3ff81872SXin Li }</b> 196*3ff81872SXin Li }</pre> 197*3ff81872SXin Li 198*3ff81872SXin Li <p>In practice, supporting this ability to mock out a factory results in 199*3ff81872SXin Li even more boilerplate code. Tests that mock out and clean up after multiple 200*3ff81872SXin Li dependencies quickly get out of hand. To make matters worse, a programmer 201*3ff81872SXin Li must predict accurately how much flexibility will be needed in the future 202*3ff81872SXin Li or else suffer the consequences. If a programmer initially elects to use a 203*3ff81872SXin Li constructor but later decides that more flexibility is required, the 204*3ff81872SXin Li programmer must replace every call to the constructor. If the programmer 205*3ff81872SXin Li errs on the side of caution and write factories up front, it may result in 206*3ff81872SXin Li a lot of unnecessary boilerplate code, adding noise, complexity, and 207*3ff81872SXin Li error-proneness. 208*3ff81872SXin Li 209*3ff81872SXin Li <p><i>Dependency injection</i> addresses all of these issues. Instead of 210*3ff81872SXin Li the programmer calling a constructor or factory, a tool called a 211*3ff81872SXin Li <i>dependency injector</i> passes dependencies to objects: 212*3ff81872SXin Li 213*3ff81872SXin Li <pre> class Stopwatch { 214*3ff81872SXin Li final TimeSource timeSource; 215*3ff81872SXin Li <b>@Inject Stopwatch(TimeSource TimeSource)</b> { 216*3ff81872SXin Li this.TimeSource = TimeSource; 217*3ff81872SXin Li } 218*3ff81872SXin Li void start() { ... } 219*3ff81872SXin Li long stop() { ... } 220*3ff81872SXin Li }</pre> 221*3ff81872SXin Li 222*3ff81872SXin Li <p>The injector further passes dependencies to other dependencies until it 223*3ff81872SXin Li constructs the entire object graph. For example, suppose the programmer 224*3ff81872SXin Li asked an injector to create a <tt>StopwatchWidget</tt> instance: 225*3ff81872SXin Li 226*3ff81872SXin Li <pre> /** GUI for a Stopwatch */ 227*3ff81872SXin Li class StopwatchWidget { 228*3ff81872SXin Li @Inject StopwatchWidget(Stopwatch sw) { ... } 229*3ff81872SXin Li ... 230*3ff81872SXin Li }</pre> 231*3ff81872SXin Li 232*3ff81872SXin Li <p>The injector might: 233*3ff81872SXin Li <ol> 234*3ff81872SXin Li <li>Find a <tt>TimeSource</tt> 235*3ff81872SXin Li <li>Construct a <tt>Stopwatch</tt> with the <tt>TimeSource</tt> 236*3ff81872SXin Li <li>Construct a <tt>StopwatchWidget</tt> with the <tt>Stopwatch</tt> 237*3ff81872SXin Li </ol> 238*3ff81872SXin Li 239*3ff81872SXin Li <p>This leaves the programmer's code clean, flexible, and relatively free 240*3ff81872SXin Li of dependency-related infrastructure. 241*3ff81872SXin Li 242*3ff81872SXin Li <p>In unit tests, the programmer can now construct objects directly 243*3ff81872SXin Li (without an injector) and pass in mock dependencies. The programmer no 244*3ff81872SXin Li longer needs to set up and tear down factories or service locators in each 245*3ff81872SXin Li test. This greatly simplifies our unit test: 246*3ff81872SXin Li 247*3ff81872SXin Li <pre> void testStopwatch() { 248*3ff81872SXin Li Stopwatch sw = new Stopwatch(new MockTimeSource()); 249*3ff81872SXin Li ... 250*3ff81872SXin Li }</pre> 251*3ff81872SXin Li 252*3ff81872SXin Li <p>The total decrease in unit-test complexity is proportional to the 253*3ff81872SXin Li product of the number of unit tests and the number of dependencies. 254*3ff81872SXin Li 255*3ff81872SXin Li <p><b>This package provides dependency injection annotations that enable 256*3ff81872SXin Li portable classes</b>, but it leaves external dependency configuration up to 257*3ff81872SXin Li the injector implementation. Programmers annotate constructors, methods, 258*3ff81872SXin Li and fields to advertise their injectability (constructor injection is 259*3ff81872SXin Li demonstrated in the examples above). A dependency injector identifies a 260*3ff81872SXin Li class's dependencies by inspecting these annotations, and injects the 261*3ff81872SXin Li dependencies at run time. Moreover, the injector can verify that all 262*3ff81872SXin Li dependencies have been satisfied at <i>build time</i>. A service locator, 263*3ff81872SXin Li by contrast, cannot detect unsatisfied dependencies until run time. 264*3ff81872SXin Li 265*3ff81872SXin Li <p>Injector implementations can take many forms. An injector could 266*3ff81872SXin Li configure itself using XML, annotations, a DSL (domain-specific language), 267*3ff81872SXin Li or even plain Java code. An injector could rely on reflection or code 268*3ff81872SXin Li generation. An injector that uses compile-time code generation may not even 269*3ff81872SXin Li have its own run time representation. Other injectors may not be able to 270*3ff81872SXin Li generate code at all, neither at compile nor run time. A "container", for 271*3ff81872SXin Li some definition, can be an injector, but this package specification aims to 272*3ff81872SXin Li minimize restrictions on injector implementations. 273*3ff81872SXin Li<P> 274*3ff81872SXin Li 275*3ff81872SXin Li<P> 276*3ff81872SXin Li<DL> 277*3ff81872SXin Li<DT><B>See Also:</B><DD><A HREF="../../javax/inject/Inject.html" title="annotation in javax.inject"><CODE>@Inject</CODE></A></DL> 278*3ff81872SXin Li<HR> 279*3ff81872SXin Li 280*3ff81872SXin Li 281*3ff81872SXin Li<!-- ======= START OF BOTTOM NAVBAR ====== --> 282*3ff81872SXin Li<A NAME="navbar_bottom"><!-- --></A> 283*3ff81872SXin Li<A HREF="#skip-navbar_bottom" title="Skip navigation links"></A> 284*3ff81872SXin Li<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY=""> 285*3ff81872SXin Li<TR> 286*3ff81872SXin Li<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> 287*3ff81872SXin Li<A NAME="navbar_bottom_firstrow"><!-- --></A> 288*3ff81872SXin Li<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY=""> 289*3ff81872SXin Li <TR ALIGN="center" VALIGN="top"> 290*3ff81872SXin Li <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../javax/inject/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A> </TD> 291*3ff81872SXin Li <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT> </TD> 292*3ff81872SXin Li <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A> </TD> 293*3ff81872SXin Li <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A> </TD> 294*3ff81872SXin Li <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A> </TD> 295*3ff81872SXin Li <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A> </TD> 296*3ff81872SXin Li </TR> 297*3ff81872SXin Li</TABLE> 298*3ff81872SXin Li</TD> 299*3ff81872SXin Li<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM> 300*3ff81872SXin Li</EM> 301*3ff81872SXin Li</TD> 302*3ff81872SXin Li</TR> 303*3ff81872SXin Li 304*3ff81872SXin Li<TR> 305*3ff81872SXin Li<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2"> 306*3ff81872SXin Li PREV PACKAGE 307*3ff81872SXin Li NEXT PACKAGE</FONT></TD> 308*3ff81872SXin Li<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2"> 309*3ff81872SXin Li <A HREF="../../index.html?javax/inject/package-summary.html" target="_top"><B>FRAMES</B></A> 310*3ff81872SXin Li <A HREF="package-summary.html" target="_top"><B>NO FRAMES</B></A> 311*3ff81872SXin Li <SCRIPT type="text/javascript"> 312*3ff81872SXin Li <!-- 313*3ff81872SXin Li if(window==top) { 314*3ff81872SXin Li document.writeln('<A HREF="../../allclasses-noframe.html"><B>All Classes</B></A>'); 315*3ff81872SXin Li } 316*3ff81872SXin Li //--> 317*3ff81872SXin Li</SCRIPT> 318*3ff81872SXin Li<NOSCRIPT> 319*3ff81872SXin Li <A HREF="../../allclasses-noframe.html"><B>All Classes</B></A> 320*3ff81872SXin Li</NOSCRIPT> 321*3ff81872SXin Li 322*3ff81872SXin Li 323*3ff81872SXin Li</FONT></TD> 324*3ff81872SXin Li</TR> 325*3ff81872SXin Li</TABLE> 326*3ff81872SXin Li<A NAME="skip-navbar_bottom"></A> 327*3ff81872SXin Li<!-- ======== END OF BOTTOM NAVBAR ======= --> 328*3ff81872SXin Li 329*3ff81872SXin Li<HR> 330*3ff81872SXin Li<font size='-1'>Copyright (C) 2009 <a href='http://code.google.com/p/atinject/'>The JSR-330 Expert Group</a>. Licensed under the <a href='http://www.apache.org/licenses/LICENSE-2.0'>Apache License</a>, Version 2.0.</font> 331*3ff81872SXin Li</BODY> 332*3ff81872SXin Li</HTML> 333