依赖注入的一点感悟
使用java的同学就算没有使用Spring,大抵也会听过这个框架的名字,Spring的核心就是依赖注入。依赖注入有什么好处,一直在想这个问题,为什么我们使用依赖注入而不是使用new 关键字。
在简单的例子中,使用new关键字是与依赖注入的方式区别不会太大,甚至使用依赖注入更加麻烦,因为还要对依赖进行配置,而且代码也要写成适合Spring的依赖注入方式,所以,为了hello world 而引人依赖注入就等于用牛刀来杀鸡了。
但是,在实际的应用中,依赖可以说是无处不在,且同一接口的不同的实现各自的依赖也会有所不同。
若一个服务的实现依赖于Spring的JdbcTemplate来访问数据库。如下:
private String doPay(String CardNum){ //do something jdbcTemplate.execute("some sql"); return "pay by card"; };
那么在使用之前,就要按照new JdbcTemplate()这样的方式来创建一个JdbcTemplate的实例,然后,我们发现JdbcTemplate依赖于javax.sql.DataSource接口,那么我们必须有一个DataSource的实例给JdbcTemplate使用。
然后我们创建的JdbcTemplate实例的方式变为new JdbcTemplate(dataSource),
进一步,我们现在到了必须关心dataSource这一个DataSource的实例怎么实例化?
若使用了容器内的数据源,这一部分数据源通常是以JNDI树的形式作为一个服务向外提供的,于是,我们写了一个专门获取数据源应用服务器数据源的代码以获取数据源。例如weblogic的数据源:
Hashtable ht = new Hashtable(); ht.put(Context.INITIAL_CONTEXT_FACTORY, “weblogic.jndi.WLInitialContextFactory"); ht.put(Context.PROVIDER_URL, "t3://127.0.0.1:7001"); Context context=new InitialContext(ht); DataSource ds = (DataSource) context.lookup("myjndi"); Connection con = ds.getConnection();
有一天,突然由于某种原因不得再使用容器了开源的数据库连接池,那么这一部分数据源就要自己维护了,比如使用c3p0,那么我们也new一个 ComboPooledDataSource的实例。
然后设置ComboPooledDataSource 的各种参数等等,然后写代码维护这个实例。。。
ComboPooledDataSource cpd = new ComboPooledDataSource(); String driverClass = "com.mysql.jdbc.Driver"; String jdbcURL = "jdbc:mysql://127.0.0.1:3306/PyaB"; String user = "PyaBDB1"; String password = "PyaBDBPass12"; cpd.setDriverClass(driverClass); cpd.setJdbcUrl(jdbcURL); cpd.setUser(user); cpd.setPassword(password); cpd.setMaxStatements(100); Connection conn = cpd.getConnection();
如上,我们本来只是想使用JdbcTemplate,现在,我们不得不关心各种DataSource了。这样,服务不得不关心更多不属于本身最重要的东西。如果依赖链非常深,使用new方式无疑是十分巨大的工作量,因为我们必须关心的东西会越来越多。
使用依赖注入的好处就是只需对依赖做好配置,实例化和注入就让容器来实现吧,如下配置:
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <bean id="payService" class="me.hockey.spring.di.service.impl.CardPayService"> <property name="jdbcTemplate" ref="jdbcTemplate"></property> </bean>
Spring便将dataSource自动注入到jdbcTemplate中,jdbcTemplate 也注入到payService中了。配置时,只需要关心与自己有关的依赖就行了。像payService只需要配置和jdbcTemplate的依赖。同时数据源更换了,只需要更改数据源的配置就行了,因为接口没有更换。
这样做的好处就是使用jdbcTemplate时候,不用关心jdbcTemplate怎么样实例化?里面的DataSource是不是已经设置好了?因为这个工作已经有正式移交给IOC容器了。就算依赖链很深也没关系,配置好,Spring同样可以帮我们自动注入进去。