今天看到spring mvc 使用Java Validation Api(JSR-303)進行校驗,需要加載一個 其具體實現(比如Hibernate Validator), 本來沒有什么問題,但是突然想到這其中到底是怎樣一種加載過程呢,也就是說spring為什么能夠找到Hibernate Validator來作為JSR-303的具體實現的呢?
1. java中的SPI機制
這篇文章對java的SPI機制講的比較容易理解,就不多做記錄. http://www.cnblogs.com/javaee6/p/3714719.html
下面的小例子,分別采用SPI機制和 反射類名的方式來獲取服務(helloApi)
首先給出服務接口,將它導出為一個jar包, hello-api.jar
package helloApi; public interface Hello { String say(); }
下面是它的一個具體實現:
package helloImpl; import helloApi.Hello; public class HelloImpl implements Hello { @Override public String say() { return "hello Massclouds"; } }
將這個實現導出為jar包,但是為了使用java 的SPI機制,我們需要在導出的jar包的META-INF中增加services文件夾,並在其中增加一個文件,以 所實現接口 helloApi.Hello 為名,以 具體實現類 helloImpl.HelloImpl為內容。
最后就是分別使用SPI和反射的方式來獲得服務。
Hello hello = null; //使用java的SPI機制加載Hello api的實現類 ServiceLoader<Hello> serviceLoader = ServiceLoader.load(Hello.class); Iterator<Hello> iter = serviceLoader.iterator(); if(iter.hasNext()){ hello = iter.next(); } System.out.println(hello.say()); //通過反射類名的方式來獲得Hello api的實現 hello = (Hello)Class.forName("helloImpl.HelloImpl").newInstance(); System.out.println(hello.say());
回過頭來考慮jdbc的加載方式,跟我上面的例子是一樣的。這兩種方式肯定是SPI更好,采用類名反射的方式本質上還是硬編碼嘛!
2. 如何加載Hibernate Validator來作為JSR-303的實現
我們打開Hibernate Validator的jar包來看看。
而這個文件的內容正是具體實現 org.hibernate.validator.HibernateValidator。至於具體Spring是怎么做的我就不詳細研究了,哈哈!!!