標籤:extc ogg 其他 name 初始化 arc return led actions
今天我分享一個技術點,利用Spring初始化+線程接管進行程式啟動後保持工作階段狀態。
先來一段@test單元測試註解,後台開發的很熟悉,這是測試局部代碼用的:
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = "classpath:applicationContext.xml")
RunWith和ContextConfiguration的源碼和功能就不細解釋了,不熟悉的可以去翻翻源碼。
1:我來一段@Test單元測試操作資料的代碼:
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = "classpath:applicationContext.xml")public class RunTest { @Autowired CustomerServices custServer;//services層,注入了dao層 @Test public void test(){ Customer customer = new Customer(); customer.setCname("餘根海"); customer.setCinfo("我是一條魚!"); customer.setCage("25"); custServer.insertTest(customer); }}
(1) 跑一遍單元測試,INFO日誌輸出:
16:34:30,296 INFO DefaultTestContextBootstrapper:259 - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]16:34:30,313 INFO DefaultTestContextBootstrapper:185 - Using TestExecutionListeners: [or[email protected]146ba0ac, org.springframework.test[email protected]4dfa3a9d, org.springframewor[email protected]6eebc39e, org.springfra[email protected]464bee09, org.springframew[email protected]f6c48ac, org.sp[email protected]13deb50e]16:34:30,390 INFO XmlBeanDefinitionReader:317 - Loading XML bean definitions from class path resource [applicationContext.xml]16:34:30,685 INFO GenericApplicationContext:578 - Refreshing [email protected]0736d9: startup date [Mon Aug 07 16:34:30 CST 2017]; root of context hierarchy16:34:30,777 INFO PropertyPlaceholderConfigurer:172 - Loading properties file from class path resource [init.properties]16:34:30,970 INFO MLog:212 - MLog clients using slf4j logging.16:34:31,123 INFO C3P0Registry:212 - Initializing c3p0-0.9.5.2 [built 08-December-2015 22:06:04 -0800; debug? true; trace: 10]16:34:31,296 INFO Version:37 - HHH000412: Hibernate Core {5.0.8.Final}16:34:31,298 INFO Environment:213 - HHH000206: hibernate.properties not found16:34:31,299 INFO Environment:317 - HHH000021: Bytecode provider name : javassist16:34:31,336 INFO Version:66 - HCANN000001: Hibernate Commons Annotations {5.0.1.Final}16:34:31,416 INFO AbstractPoolBackedDataSource:212 - Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 5, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 30000, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> 1bqudj89p1g46yu313x3lsl|41ab013, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 1bqudj89p1g46yu313x3lsl|41ab013, idleConnectionTestPeriod -> 30, initialPoolSize -> 5, jdbcUrl -> jdbc:mysql://127.0.0.1:3306/yugh?useUnicode=true&characterEncoding=utf-8, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 30, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 20, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 5, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]16:34:31,633 INFO Dialect:156 - HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect16:34:31,671 INFO LobCreatorBuilderImpl:98 - HHH000423: Disabling contextual LOB creation as JDBC driver reported JDBC version [3] less than 416:34:32,027 INFO SchemaUpdate:105 - HHH000228: Running hbm2ddl schema update16:34:32,120 INFO HibernateTransactionManager:357 - Using DataSource [com.mchange.v2.c3p0.ComboPooledDataSource[ identityToken -> 1bqudj89p1g46yu313x3lsl|41ab013, dataSourceName -> 1bqudj89p1g46yu313x3lsl|41ab013 ]] of Hibernate SessionFactory for HibernateTransactionManagerHibernate: select next_val as id_val from hibernate_sequence for updateHibernate: update hibernate_sequence set next_val= ? where next_val=?Hibernate: insert into customer (cage, cinfo, cname, id) values (?, ?, ?, ?)16:34:32,487 INFO GenericApplicationContext:960 - Closing [email protected]0736d9: startup date [Mon Aug 07 16:34:30 CST 2017]; root of context hierarchy
(2) 可以看到@Test單元測試初始化了一遍Spring和Spring檔案裡的所有配置,因為要操作資料對象,在大部分後台單元測試中,目的都是資料互動。
@Test總結:通過@Test單元測試可以得到初始化Spring以及載入完畢已經配置到Spring檔案中所有正確的配置參數,雖然它運行是短暫的。
請忽略上面的Hibernate,雖然上面測試是hibernate作為持久層,但本文所有知識點都是Spring,包括用Spring的資料控制替換其他持久層。
2:得到了初始化的目的,下面就得用線程接管初始化後的操作,幾個關鍵點:(1)初始化spring檔案 (2)事務用誰,怎麼用,能否成功?(3)線程何時去接管?
靜態對象是保持對象唯一,保持初始化的唯一,因為用@TEST單元測試時候,註解RunWith是把測試類別和方法名都反射了,已經得到了真實的功能類入口,而我們自己初始化Spring啟動程式不用@TEST註解就要定義全域靜態對象。
(1):初始化Spring檔案,檔案載入方式是我常用的:
public static final ApplicationContext CONTEXT = new ClassPathXmlApplicationContext("applicationContext.xml");
(2):事務採用Spring的:dataSource是資料庫的bean
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"> <ref bean="dataSource" /> </property> </bean>
寫下擷取事務的靜態對象:
static final PlatformTransactionManager MANAGER = (PlatformTransactionManager)CONTEXT.getBean("transactionManager");
(3):資料控制對象jdbctemplate,前身jdbcAccessor,源碼用的基於sql的DataSource:
public static final JdbcTemplate JDBC_TEMPLATE = (JdbcTemplate)CONTEXT.getBean("jdbcTemplate");
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource"> <ref bean="dataSource" /> </property> </bean>
(4) 到這裡的配置菜單有:初始化Spring檔案 + 事務 + 資料控制對象,雖然全部依賴Spring,但已經是一個很優秀的純後台項目架構了,雖然在持久層沒有hibernate那麼強大各種操作方式。
最後來一段Spring初始化日誌:
09:43:35,326 INFO ClassPathXmlApplicationContext:578 - Refreshing org[email protected]7ce6a65d: startup date [Tue Aug 08 09:43:35 CST 2017]; root of context hierarchy09:43:35,368 INFO XmlBeanDefinitionReader:317 - Loading XML bean definitions from class path resource [applicationContext.xml]09:44:21,994 INFO PropertyPlaceholderConfigurer:172 - Loading properties file from class path resource [init.properties]09:44:24,847 INFO MLog:212 - MLog clients using slf4j logging.09:44:25,007 INFO C3P0Registry:212 - Initializing c3p0-0.9.5.2 [built 08-December-2015 22:06:04 -0800; debug? true; trace: 10]09:44:33,517 INFO AbstractPoolBackedDataSource:212 - Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 5, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 30000, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> 1bqudj89p1h4zfam1rricvn|62e8f862, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 1bqudj89p1h4zfam1rricvn|62e8f862, idleConnectionTestPeriod -> 30, initialPoolSize -> 5, jdbcUrl -> jdbc:mysql://127.0.0.1:3306/yugh?useUnicode=true&characterEncoding=utf-8, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 30, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 20, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 5, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]
總結構思:(1)利用代碼初始載入Spring檔案 ——> (2)主入口定義一個main方法,各種校正運行後,運行 ——> (3)調用靜態初始化代碼,開始初始 ——> (4) 初始完畢後調用資料控制 ——> (5)通過一系列後台操作後,線程開始接管 ——> (6)代碼控制它保持後台運行工作階段狀態。
Spring初始化ApplicationContext線程託管實際運用架構構思