如果数据库不经常更改,则可以使用数据库的 JDBC 驱动程序附带的数据源,并在提供程序中隔离对第三方库的调用(我的示例使用 H2 dataabse 提供的数据源,但所有 JDBC 提供程序都应该有一个)。如果更改为数据源的其他实现(例如 c3PO、Apache DBCP 或应用服务器容器提供的实现),则只需编写新的提供程序实现即可从适当的位置获取数据源。在这里,我使用单一实例范围来允许在依赖于它的那些类之间共享DataSource实例(这是池化所必需的)。
public class DataSourceModule extends AbstractModule {
    @Override
    protected void configure() {
        Names.bindProperties(binder(), loadProperties());
        bind(DataSource.class).toProvider(H2DataSourceProvider.class).in(Scopes.SINGLETON);
        bind(MyService.class);
    }
    static class H2DataSourceProvider implements Provider<DataSource> {
        private final String url;
        private final String username;
        private final String password;
        public H2DataSourceProvider(@Named("url") final String url,
                                    @Named("username") final String username,
                                    @Named("password") final String password) {
            this.url = url;
            this.username = username;
            this.password = password;
        }
        @Override
        public DataSource get() {
            final JdbcDataSource dataSource = new JdbcDataSource();
            dataSource.setURL(url);
            dataSource.setUser(username);
            dataSource.setPassword(password);
            return dataSource;
        }
    }
    static class MyService {
        private final DataSource dataSource;
        @Inject
        public MyService(final DataSource dataSource) {
            this.dataSource = dataSource;
        }
        public void singleUnitOfWork() {
            Connection cn = null;
            try {
                cn = dataSource.getConnection();
                // Use the connection
            } finally {
                try {
                    cn.close();
                } catch (Exception e) {}
            }
        }
    }
    private Properties loadProperties() {
        // Load properties from appropriate place...
        // should contain definitions for:
        // url=...
        // username=...
        // password=...
        return new Properties();
    }
}
若要处理事务,应使用事务感知数据源。我不建议手动实现它。使用诸如warp-persist或容器提供的事务管理之类的东西,但是它看起来像这样:
public class TxModule extends AbstractModule {
    @Override
    protected void configure() {
        Names.bindProperties(binder(), loadProperties());
        final TransactionManager tm = getTransactionManager();
        bind(DataSource.class).annotatedWith(Real.class).toProvider(H2DataSourceProvider.class).in(Scopes.SINGLETON);
        bind(DataSource.class).annotatedWith(TxAware.class).to(TxAwareDataSource.class).in(Scopes.SINGLETON);
        bind(TransactionManager.class).toInstance(tm);
        bindInterceptor(Matchers.any(), Matchers.annotatedWith(Transactional.class), new TxMethodInterceptor(tm));
        bind(MyService.class);
    }
    private TransactionManager getTransactionManager() {
        // Get the transaction manager
        return null;
    }
    static class TxMethodInterceptor implements MethodInterceptor {
        private final TransactionManager tm;
        public TxMethodInterceptor(final TransactionManager tm) {
            this.tm = tm;
        }
        @Override
        public Object invoke(final MethodInvocation invocation) throws Throwable {
            // Start tx if necessary
            return invocation.proceed();
            // Commit tx if started here.
        }
    }
    static class TxAwareDataSource implements DataSource {
        static ThreadLocal<Connection> txConnection = new ThreadLocal<Connection>();
        private final DataSource ds;
        private final TransactionManager tm;
        @Inject
        public TxAwareDataSource(@Real final DataSource ds, final TransactionManager tm) {
            this.ds = ds;
            this.tm = tm;
        }
        public Connection getConnection() throws SQLException {
            try {
                final Transaction transaction = tm.getTransaction();
                if (transaction != null && transaction.getStatus() == Status.STATUS_ACTIVE) {
                    Connection cn = txConnection.get();
                    if (cn == null) {
                        cn = new TxAwareConnection(ds.getConnection());
                        txConnection.set(cn);
                    }
                    return cn;
                } else {
                    return ds.getConnection();
                }
            } catch (final SystemException e) {
                throw new SQLException(e);
            }
        }
        // Omitted delegate methods.
    }
    static class TxAwareConnection implements Connection {
        private final Connection cn;
        public TxAwareConnection(final Connection cn) {
            this.cn = cn;
        }
        public void close() throws SQLException {
            try {
                cn.close();
            } finally {
                TxAwareDataSource.txConnection.set(null);
            }
        }
        // Omitted delegate methods.
    }
    static class MyService {
        private final DataSource dataSource;
        @Inject
        public MyService(@TxAware final DataSource dataSource) {
            this.dataSource = dataSource;
        }
        @Transactional
        public void singleUnitOfWork() {
            Connection cn = null;
            try {
                cn = dataSource.getConnection();
                // Use the connection
            } catch (final SQLException e) {
                throw new RuntimeException(e);
            } finally {
                try {
                    cn.close();
                } catch (final Exception e) {}
            }
        }
    }
}