如果您使用該框架已經超過一個月,那么在這篇回顧性文章中可能不會發現任何有趣的東西。 除了Scala中的最后一個示例,沒有其他希望,這種語言在Spring中意外地很好用。
首先是XML [ 全文 ]:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd "><bean id="foo" class="com.blogspot.nurkiewicz.Foo"><property name="bar" ref="bar"/><property name="jdbcOperations" ref="jdbcTemplate"/></bean><bean id="bar" class="com.blogspot.nurkiewicz.Bar" init-method="init"/><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"><property name="driverClassName" value="org.h2.Driver"/><property name="url" value="jdbc:h2:mem:"/><property name="username" value="sa"/></bean><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><constructor-arg ref="dataSource"/></bean>
</beans>
這個簡單的應用程序僅獲取H2數據庫服務器時間并以完整格式打印它:
public class Foo {private Bar bar;private JdbcOperations jdbcOperations;public String serverTime() {return bar.format(jdbcOperations.queryForObject("SELECT now()", Date.class));}public void setBar(Bar bar) {this.bar = bar;}public void setJdbcOperations(JdbcOperations jdbcOperations) {this.jdbcOperations = jdbcOperations;}
}
public class Bar {private FastDateFormat dateFormat;public void init() {dateFormat = FastDateFormat.getDateTimeInstance(FULL, FULL);}public String format(Date date) {return dateFormat.format(date);}
}
這段代碼有些令人不安。 首先,令人驚訝的是有很多XML。 與類似的EJB 2.1應用程序相比,它仍然要少一些(此代碼在2006年的Spring 1.2.6上進行了微小的更改 ),但是感覺很不對。 公共設置者更加令人不安–為什么我們被迫在任何時候任何人都公開覆蓋對象依賴的能力? 順便說一下,我從來沒有真正理解過為什么為什么在使用tag時Spring不允許直接將依賴項注入到私有字段中,因為這樣做可能……
批注 [ 全文 ]
Java 5和Spring 2.5帶來了對注釋驅動的依賴注入的支持:
<context:annotation-config/><!-- or even: --><context:component-scan base-package="com.blogspot.nurkiewicz"/>
從第一行開始,您不再需要在XML中定義<property>標簽,只需定義<bean>。 該框架將獲取標準的@Resource注釋。 將其替換為第二行,甚至根本不需要在XML中指定bean:
@Service
public class Foo {@Resourceprivate Bar bar;@Resourceprivate JdbcOperations jdbcOperations;public String serverTime() {return bar.format(jdbcOperations.queryForObject("SELECT now()", Date.class));}
}
@Service
public class Bar {private FastDateFormat dateFormat;@PostConstructpublic void init() {dateFormat = FastDateFormat.getDateTimeInstance(FULL, FULL);}public String format(Date date) {return dateFormat.format(date);}
}
當然,您不會留下深刻的印象! 尼爾·諾維(Nihil Novi) 。 另外,我們仍然必須使用XML,因為我們無法控制第三方類(例如數據源和JdbcTemplate ),因此無法對其進行注釋。 但是Spring 3.0引入了:
@Configuration [ 完整源代碼 ]
我已經在探索@ Configuration / @ Bean支持,因此這次請重點關注如何啟動應用程序上下文。 您看到對XML文件的任何引用嗎? applicationContext.xml描述符完全消失了:
@ComponentScan("com.blogspot.nurkiewicz")
public class Bootstrap {private static final Logger log = LoggerFactory.getLogger(Bootstrap.class);@Beanpublic DataSource dataSource() {final BasicDataSource dataSource = new BasicDataSource();dataSource.setDriverClassName("org.h2.Driver");dataSource.setUrl("jdbc:h2:mem:");dataSource.setUsername("sa");return dataSource;}@Beanpublic JdbcTemplate jdbcTemplate() {return new JdbcTemplate(dataSource());}public static void main(String[] args) {final AbstractApplicationContext applicationContext = new AnnotationConfigApplicationContext(Bootstrap.class);final Foo foo = applicationContext.getBean(Foo.class);log.info(foo.serverTime());applicationContext.close();}
}
如您所見,Spring從使用大量XML到不使用XML的框架走了很長的路。 但最令人興奮的部分是您可以使用喜歡的任何樣式,甚至可以將它們混合使用。 您可以使用舊版Spring應用程序并開始使用批注或切換到XML,因為上帝知道這里或那里的原因。
我沒有提到的一種技術是構造函數注入。 它有一些很大的好處(請參閱使用構造函數進行依賴注入? ),例如將依賴關系標記為最終的并禁止創建未初始化對象的能力:
@Service
public class Foo {private final Bar bar;private final JdbcOperations jdbcOperations;@Autowiredpublic Foo(Bar bar, JdbcOperations jdbcOperations) {this.bar = bar;this.jdbcOperations = jdbcOperations;}//...}
我希望構造函數注入,但是再次感到有點失望。 每個對象依賴項都需要(a)構造函數參數,(b)最終字段和(c)構造函數中的賦值操作。 我們最后得到十行代碼,這些行什么都不做。 這個健談的代碼克服了所有優點。 當然,任何對象都不應具有超過(在這里輸入您的數字)的依賴關系-借助構造函數注入,您會立即看到該對象具有太多的依賴關系-但我仍然發現此代碼引入了太多的儀式。
用Scala注入Spring構造函數 [ 完整源代碼 ]
Scala的一個功能完全適合Spring框架:默認情況下,任何Scala對象的每個參數都會創建與該參數相同的最終字段。 對我們而言,這意味著什么? 看看翻譯成Scala的Foo類:
@Service
class Foo @Autowired() (bar: Bar, jdbcOperations: JdbcOperations) {def serverTime() = bar.format(jdbcOperations.queryForObject("SELECT now()", classOf[Date]))}
認真嗎 但是……怎么了? 在這里深入了解Scala的優勢之前,請看一下Java反編譯器生成的等效Java代碼:
@Service
public class Foo implements ScalaObject
{private final Bar bar;private final JdbcOperations jdbcOperations;@Autowiredpublic Foo(Bar bar, JdbcOperations jdbcOperations){this.bar = bar;this.jdbcOperations = jdbcOperations;}public String serverTime(){return this.bar.format(this.jdbcOperations.queryForObject("SELECT now()", Date.class));}}
與我們用Java編寫的代碼幾乎完全相同。 擁有所有優勢:依賴最終將使我們的服務真正不變和無狀態; 依賴是私有的,不會暴露給外界; 實際上,不需要額外的代碼來管理依賴項:只需添加構造函數參數,Scala就會處理其余的工作。
總結一下–您擁有廣泛的可能性。 從XML到Java代碼再到Scala。 最后一種方法實際上很誘人,因為它使您擺脫了所有樣板,并使您可以專注于業務功能。 完整的源代碼可在我的GitHub存儲庫中找到,每個步驟都帶有標簽,因此您可以比較和選擇最喜歡的方法。
參考資料: NoBlogDefFound的JCG合作伙伴Tomek Nurkiewicz提供的Spring依賴注入技術的 發展
編碼愉快! 不要忘記分享!
相關文章:
- Java最佳實踐系列
- 正確記錄應用程序的10個技巧
- 每個程序員都應該知道的事情
- 生存在狂野西部開發過程中的9條提示
- 軟件設計法則
- Java Fork / Join進行并行編程
翻譯自: https://www.javacodegeeks.com/2011/09/evolution-of-spring-dependency.html