spring MethodInvokingFactoryBean 的使用和了解,Spring 通過通過方法建立Bean的例項
spring MethodInvokingFactoryBean 的使用和了解
作用
- 讓某個例項的某個方法的返回值注入為Bean的例項
- 讓某個類的靜態方法的返回值注入為Bean的例項
使用MethodInvokingFactoryBean
- 使用IDEA Maven專案非常方便的下載原始碼檢視其類的說明資訊,在這裡非常方便的可以檢視到這個方法的一些使用的說明
- 小測試一下子,簡單的就跟著這個使用的作用的兩個方法進行使用一下吧
資源不如下面建立一個:spring-methodInvoking.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.xsd">
<!--呼叫靜態方法的返回值作為bean-->
<bean id="sysProps" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass" value="java.lang.System"/>
<property name="targetMethod" value="getProperties"/>
</bean>
<!--呼叫例項方法的返回值作為bean-->
<bean id="javaVersion" class ="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="sysProps"/>
<property name="targetMethod" value="getProperty"/>
<property name="arguments" value="java.version"/>
</bean>
</beans>
下面是System中的靜態方法的返回值Properties包含配置的屬性的檔案的資訊,相當於呼叫靜態方法
然後在呼叫生成的Properties這個Bean的例項的方法的某個屬性
public static Properties getProperties() {
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPropertiesAccess();
}
return props;
}
測試
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
import java.util.Properties;
/**
* descrption:
* authohr: wangji
* date: 2017-08-24 13:35
*/
@Slf4j
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={
"classpath:spring-methodInvoking.xml"})
public class MethodTest extends AbstractJUnit4SpringContextTests{
@Resource(name = "sysProps")
public Properties properties;
@Resource(name ="javaVersion")
public String javaVersion;
@Test
public void test(){
log.info(properties.toString());
log.info(javaVersion.toString());
}
}
//2017-08-24 14:03:26,142 INFO [MethodTest.java:31] : {java.runtime.name=Java(TM) SE Runtime Environment,
// sun.boot.library.path=D:\Program Files\Java\jdk1.8.0_101\jre\bin, java.vm.version=25.101-b13,
//........
// java.library.path=D:\Program Files\Java\jdk1.8.0_101\bin;
// C:\Windows\Sun\Java\bin;C:\Windows\system32;
// C:\Windows;D:\Program Files\Java\jdk1.8.0_101\bin;
//2017-08-24 14:03:26,145 INFO [MethodTest.java:32] : 1.8.0_101
測試總結
測試結果如同我們想象的一樣,可以將某個方法或者某個具體的類的靜態方法進行呼叫
因為我們總會呼叫這個方法,相當於初始化方法唄,對於返回值,你可以隨便返回一個Boolean 這個就將這個Boolean的值注入到了
spring的容器中去了,不過這個不是最好的手段,你可以繼承InitializingBean,或者使用註解@PostConstruct,在初始化Bean之前呼叫這個方法
但是有些時候不想初始化某個Bean你還是可以這麼幹的。
會使用開發中很重要,知其所以然也是很重要(瞭解這個背後實現的故事)
- 繼承圖
剛剛上面說了MethodInvokingFactoryBean將呼叫方法的返回值注入為Bean,我不注入可以?
可以的,其實就是呼叫剛剛那個類的父類MethodInvokingBean,呼叫某個靜態的方法,呼叫某個類的例項的方法都可以
最後將MethodInvokingBean注入為Bean其實原理是差不多的。
<bean id="testBean" class="org.springframework.beans.factory.config.MethodInvokingBean">
<property name="staticMethod" value="com.common.utils.test.MethodInvokingBeanTest.test"></property>
</bean>
package com.common.utils.test;
import lombok.extern.slf4j.Slf4j;
/**
* descrption:測試呼叫靜態方法不注入Bean
* authohr: wangji
* date: 2017-08-24 14:20
*/
@Slf4j
public class MethodInvokingBeanTest {
public static void test(){
log.info("呼叫了這個方法");
}
}
@Resource(name = "testBean")
public MethodInvokingBean methodInvokingBean;
@Test
public void testMethod(){
log.info(methodInvokingBean.getTargetMethod());
}
// 2017-08-24 14:25:52,229 INFO [MethodInvokingBeanTest.java:15] : 呼叫了這個方法
// 2017-08-24 14:25:52,243 INFO [MethodTest.java:34] : test
繼續看MethodInvokingBean的實現的原理
MethodInvokingBean實現了InitializingBean方法,Bean在初始化的時候會首先呼叫這個介面的實現,然後在初始化Bean
@Override
public void afterPropertiesSet() throws Exception {
prepare();
invokeWithTargetException();
}
呼叫父類MethodInvoker的prepare方法,進行校驗傳遞的引數是否正確,因為有兩種不同的搭配,靜態和例項方法
- MethodInvoker的成員變數可以看出來
private Class<?> targetClass;//目標Class
private Object targetObject;//目標Object
private String targetMethod;//例項的方法
private String staticMethod;//靜態的方法
private Object[] arguments = new Object[0];
/** The method we will call */
private Method methodObject; //需要呼叫的方法
- 準備函式(校驗和設定呼叫的methObject,然後通過反射呼叫方法,無論是靜態還是非靜態的函式,靜態的method.invoke(null, 引數),第一個傳遞為NULL
public void prepare() throws ClassNotFoundException, NoSuchMethodException {
if (this.staticMethod != null) {
int lastDotIndex = this.staticMethod.lastIndexOf('.');
if (lastDotIndex == -1 || lastDotIndex == this.staticMethod.length()) {
throw new IllegalArgumentException(“必須使用全限定名")
}
String className = this.staticMethod.substring(0, lastDotIndex);
String methodName = this.staticMethod.substring(lastDotIndex + 1);
this.targetClass = resolveClassName(className);//反射找到型別
this.targetMethod = methodName;//要呼叫的方法的名稱
}
Class<?> targetClass = getTargetClass();
String targetMethod = getTargetMethod();
if (targetClass == null) {
throw new IllegalArgumentException("Either 'targetClass' or 'targetObject' is required");
}
if (targetMethod == null) {
throw new IllegalArgumentException("Property 'targetMethod' is required");
}
Object[] arguments = getArguments();
Class<?>[] argTypes = new Class<?>[arguments.length];//根據傳遞的引數找到,引數的型別
for (int i = 0; i < arguments.length; ++i) {
argTypes[i] = (arguments[i] != null ? arguments[i].getClass() : Object.class);
}
// Try to get the exact method first.
try {
this.methodObject = targetClass.getMethod(targetMethod, argTypes);
}
catch (NoSuchMethodException ex) {
// Just rethrow exception if we can't get any match.
this.methodObject = findMatchingMethod();//可能位置不對,沒有找到方法
if (this.methodObject == null) {
throw ex;
}
}
}
- invokeWithTargetException();函式還是一樣的,呼叫MethodInvoker的invoke函式,獲取之前得到的需要反射的方法,這裡會有靜態和例項方法的區別,靜態的targetObject為空
public Object invoke() throws InvocationTargetException, IllegalAccessException {
// In the static case, target will simply be {@code null}.
Object targetObject = getTargetObject();
Method preparedMethod = getPreparedMethod();
if (targetObject == null && !Modifier.isStatic(preparedMethod.getModifiers())) {
throw new IllegalArgumentException("not be non-static without a target");
}
ReflectionUtils.makeAccessible(preparedMethod);
return preparedMethod.invoke(targetObject, getArguments());
}
- 設定方法反射的可呼叫性,看類是不是私有的,方法是不是私有的,方法的訪問性等等等!可以通過Modifier進行判斷
/**
* Make the given method accessible, explicitly setting it accessible if
* necessary. The {@code setAccessible(true)} method is only called
* when actually necessary, to avoid unnecessary conflicts with a JVM
* SecurityManager (if active).
* @param method the method to make accessible
* @see java.lang.reflect.Method#setAccessible
*/
public static void makeAccessible(Method method) {
if ((!Modifier.isPublic(method.getModifiers()) ||
!Modifier.isPublic(method.getDeclaringClass().getModifiers()))
&& !method.isAccessible()) {
method.setAccessible(true);
}
}
- 呼叫完了,沒有對於返回的返回值進行處理,這樣就完了!MethodInvokingBean,這個也是他的子類MethodInvokingFactoryBean的區別,MethodInvokingFactoryBean將會把返回的值注入為Bean的物件
- MethodInvokingBean將自己註冊為Bean啦,他的子類MethodInvokingFactoryBean也將註冊為Bean的例項,但是實際通過getBean呼叫的時候會將MethodInvokingFactoryBean.getObject作為結果返回給呼叫的物件,這個檢視原始碼的時候會很清楚。
MethodInvokingFactoryBean的實現的原理
- 繼承了之前的MethodInvokingBean,處理邏輯還是類似的,只是增加了一些判斷,還有實現了一個介面FactoryBean(當前工廠是一個Bean的例項)FactoryBean這個介面很神奇,當實現了這個介面的時候,不會將當前的例項註冊為Bean,而是註冊getObject這個函式的返回值註冊為SpringIO中的Bean具體的為什麼稍後在說。
public interface FactoryBean<T> {
/**
* Return an instance (possibly shared or independent) of the object
* managed by this factory.
* <p>As with a {@link BeanFactory}, this allows support for both the
* Singleton and Prototype design pattern.
* <p>If this FactoryBean is not fully initialized yet at the time of
* the call (for example because it is involved in a circular reference),
* throw a corresponding {@link FactoryBeanNotInitializedException}.
* <p>As of Spring 2.0, FactoryBeans are allowed to return {@code null}
* objects. The factory will consider this as normal value to be used; it
* will not throw a FactoryBeanNotInitializedException in this case anymore.
* FactoryBean implementations are encouraged to throw
* FactoryBeanNotInitializedException themselves now, as appropriate.
* @return an instance of the bean (can be {@code null})
* @throws Exception in case of creation errors
* @see FactoryBeanNotInitializedException
*/
T getObject() throws Exception;
Class<?> getObjectType();
boolean isSingleton();
}
- 覆蓋了父類MethodInvokingBean的初始化方法afterPropertiesSet
- MethodInvokingFactoryBean 成員變數資訊
private boolean singleton = true;
private boolean initialized = false;
/** Method call result in the singleton case */
private Object singletonObject;
- 覆蓋後的afterPropertiesSet方法(建立Bean之前會呼叫)
添加了是不是單例的判斷,將反射呼叫的返回值儲存了下來
public void afterPropertiesSet() throws Exception {
prepare();//MethodInvoker準備函式
if (this.singleton) {
this.initialized = true;
this.singletonObject = invokeWithTargetException();//函式呼叫方法的返回值儲存下來
}
}
- 完整的方法(現在的問題就是為啥繼承了FactoryBean,我們通過getBean呼叫的時候會將getObject的返回值注入Spring Bean,而不是返回當前的FactoryBean的例項)
public class MethodInvokingFactoryBean extends MethodInvokingBean implements FactoryBean<Object> {
private boolean singleton = true;
private boolean initialized = false;
private Object singletonObject;
public void setSingleton(boolean singleton) {
this.singleton = singleton;
}
@Override
public void afterPropertiesSet() throws Exception {
prepare();
if (this.singleton) {
this.initialized = true;
this.singletonObject = invokeWithTargetException();
}
}
/**
* Returns the same value each time if the singleton property is set
* to "true", otherwise returns the value returned from invoking the
* specified method on the fly.
*/
@Override
public Object getObject() throws Exception {
//獲取那個返回值,也就是當前由於繼承了FactoryBean介面,獲取到的Bean將是反射方法的返回的結果
if (this.singleton) {
if (!this.initialized) {
throw new FactoryBeanNotInitializedException();
}
// Singleton: return shared object.
return this.singletonObject;
}
else {
// Prototype: new object on each call.
return invokeWithTargetException();
}
}
/**
* Return the type of object that this FactoryBean creates,
* or {@code null} if not known in advance.
*/
@Override
public Class<?> getObjectType() {//Bean例項的型別,就是反射呼叫返回值的型別
if (!isPrepared()) {
// Not fully initialized yet -> return null to indicate "not known yet".
return null;
}
return getPreparedMethod().getReturnType();
}
@Override
public boolean isSingleton() {
return this.singleton;
}
}
FactoryBean
簡單的聊聊
- 由spring的bean容器管理的並且實現了FactoryBean介面的類例項本身也是一個Spring IOC中的一個Bean,通過spring的bean容器的getBean()方法獲得bean例項時,實際上獲得的是這個FactoryBean生產出來的例項對像(也就是getObject返回的物件),而非這個FactoryBean例項的本身。
- 但在getBean()指定的beanName前加上”&”符號就獲得了這個FactoryBean的例項的本身,在spring框架中就有很多地方使用了FactoryBean。例如 org.springframework.aop.framework.ProxyFactoryBean等.框架中有很多的類似的實現
- BeanFactory: 以Factory結尾,表示它是一個工廠類,是用於管理Bean的一個工廠
- FactoryBean:以Bean結尾,表示它是一個Bean,不同於普通Bean的是,它是實現了FactoryBean< T>介面的Bean,根據該Bean的Id從BeanFactory中獲取的實際上是FactoryBean的getObject()返回的物件,而不是FactoryBean本身, 如果要獲取FactoryBean物件,可以在id前面加一個&符號來獲取。
- 一般情況下,Spring通過反射機制利用bean的class屬性指定實現類來例項化bean 。在某些情況下,例項化bean過程比較複雜,如果按照傳統的方式,則需要在bean中提供大量的配置資訊,配置方式的靈活性是受限的,這時採用編碼的方式可能會得到一個簡單的方案。Spring為此提供了一個org.Springframework.bean.factory.FactoryBean的工廠類介面,使用者可以通過實現該介面定製例項化bean的邏輯。
http://www.cnblogs.com/davidwang456/p/3688250.html/ FacroryBean的使用
看看怎麼對於特殊的FacoryBean< T> 獲取Bean呢?特殊的Bean哦!
- AbstractBeanFactory的繼承圖
- getBean的邏輯
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
doGetBean中會呼叫bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
//如果是對FactoryBean的解引用(&繼承FactoryBean,找真實的FactoryBean),
//但bean物件不是FactoryBean,丟擲異常
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
//如果Bean例項不是FactoryBean,或者指定名稱是FactoryBean的解引用,
//也就是普通的bean呼叫,則直接返回當前的Bean例項
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
//處理對FactoryBean的呼叫
Object object = null;
if (mbd == null) {
//從FactoryBean快取中獲取給定名稱的例項物件
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean factory = (FactoryBean) beanInstance;
//如果從FacroryBean生產的Bean是單態模式的,則快取
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
//呼叫FactoryBeanRegistrySupport(FactoryBean快取倉庫支援類)
//的getObjectFromFactoryBean方法,實現FactoryBean生產Bean物件例項的過程
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
- 獲取Bean的邏輯
Object object = this.factoryBeanObjectCache.get(beanName);//快取倉庫中存在?
object = doGetObjectFromFactoryBean(factory, beanName);//不存在價值從FactoryBean的例項中載入
- 全部程式碼
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object = doGetObjectFromFactoryBean(factory, beanName);
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (object != null && shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
//...
}
}
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
}
}
return (object != NULL_OBJECT ? object : null);
}
}
else {
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (object != null && shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
//.....
}
}
return object;
}
}
- doGetObjectFromFactoryBean,從FactoryBean的例項中獲取getObject
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException {
//......
object = factory.getObject();
return object;
}
- 這樣的實現類很多,FactoryBean看圖
總結
今天對於FactoryBean的原理進行了瞭解,也對於MethodInvokingFactoryBean的使用進行了瞭解,可以非常方便的將某個方法的返回值弄成Bean的例項
多看看,多總結,提升就在不經意之間, 或許還有很多不懂的地方,請多多指教,畢竟Spring的程式碼太大,我們只能慢慢的看,慢慢的瞭解。
類似這樣MethodInvokingFactoryBean例項化類比較複雜的使用這個應該還是比較的簡單吧!
相關推薦
spring MethodInvokingFactoryBean 的使用和了解,Spring 通過通過方法建立Bean的例項
spring MethodInvokingFactoryBean 的使用和了解 作用 讓某個例項的某個方法的返回值注入為Bean的例項 讓某個類的靜態方法的返回值注入為Bean的例項 使用MethodInvokingFactoryBean
Spring-02 -Spring 建立物件的三種方式 :1.通過構造方法建立/2.例項工廠/3.靜態工廠
通過構造方法建立 1.1 無參構造建立:預設情況. 1.2 有參構造建立:需要明確配置 1.2.1 需要在類中提供有參構造方法 1.2.2 在 applicationContext.x
深入學習Spring框架之五通過工廠方法建立Bean
前面我們介紹了,通過構造器的方式建立Bean物件,今天我們來講一下通過工廠方法來建立Bean。 有些時候,我們有必要將一些類設定為單例模式,比如說一個國家的最高領導人,再比如我們在銀行
輕松了解Spring中的控制反轉和依賴註入(一)
xml文件 span 做到 添加 resource exce http 實的 name 原文轉自:https://www.cnblogs.com/xxzhuang/p/5948902.html 我們回顧一下計算機的發展史,從最初第一臺計算機的占地面積達170平方米,重達
Spring--1簡單了解
組裝 cnblogs http src 邏輯 自己 -- 技術 .com spring容器類型: spring定義: spring通過DI,AOP,消除樣板試代碼,簡化企業級java開發。促進代碼松散耦合,成功的關鍵在於依賴註入,aop。 spring框架最核心的部分:
以Spring整合EhCache為例從根本上了解Spring緩存這件事(轉)
內置 tor 重要 date 清單 one display 結合 boa 前兩節“Spring緩存抽象”和“基於註解驅動的緩存”是為了更加清晰的了解Spring緩存機制,整合任何一個緩存實現或者叫緩存供應商都應該了解並清楚前兩
三分鐘輕松了解Spring框架基礎知識
xmla 深入 dao reference inject ace eve con 說過 做為一個合格的Java開發人員,你一定聽說過Spring框架,雖然會應用,但卻未必能夠深入理解框架的原理,只是像其它人一樣,泛泛的只是停留在理解的層面。小編會帶著大家一步步了解Sprin
小編帶你了解Spring Cloud 微服務
做到 隨著 減少 工具包 註冊 其它 系統開發 onf 數據 Spring Cloud 簡介 Spring Cloud是一系列框架的有序集合。它利用Spring Boot的開發便利性巧妙地簡化了分布式系統基礎設施的開發,如服務發現註冊、配置中心、消息總線、負載均衡、斷
Spring通過工廠方法配置Bean
前言: Spring配置Bean的方法有很多,這裡只介紹通過工廠方法配置Bean。 所謂工廠即含有批量的Bean,可根據傳入的引數條件返回對應的Bean例項。 工廠又分兩種: 靜態工廠通過靜態方
(轉)spring源碼解析,深入了解spring
運動 重要 art point ioe 魔方 父類 prototype processor 轉自:https://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/ Spring 的骨骼架構 Spring 總共
了解spring的AOP實現的必要基礎
三種 得到 一個 發包 模式 字節碼 syn 性能 和我 動態代理又分為jdk動態代理和cglib動態代理,兩者的區別是jdk動態代理的實現是基於接口,http://www.ukmtey.com/ 而cglib動態代理是基於繼承,但兩者做的是同一件事,那就是字節碼重組。 基
spring通過呼叫靜態工廠方法建立Bean
一:靜態工廠方法 1.呼叫靜態工廠方法建立Bean是將物件建立Bean的建立過程封裝到靜態方法中,當客戶端需要物件時,只需要簡單的呼叫靜態方法,而不關心建立物件的細節。 2.要宣告通過靜態方法建立的Bean,需要在Bean的class屬性裡指定擁有該工廠方法的類,同時在factory-met
Spring整理系列(17)————循序漸進了解spring事務管理的幾種方式
先從例項開始。。。。 一、例項基本業務為銀行轉賬,A賬戶向B賬戶轉賬,業務執行過程要保證A、B兩個帳號資料操作同時成功或失敗,此時就需要事務進行控制,基本例項程式碼如下: 轉賬DAO: public interface AccountDao {
深入了解spring(一) spring的作用
java項目 處的 基於 實現 pojo 技術 sdn 架構 作用 spring是為了簡單的開發的Java項目,是一個輕量級的框架 1.基於pojo的清亮級和小侵入式編程。不用像某些重量級框架一樣必須繼承接口或實現規範的類 2.通過IOC的依賴註入可以在多個類之間降低耦合
認識和了解python
pytho odi ron 區分 put 代碼 大小寫 大寫 1年 一: Python介紹 1.1 python創始人吉多.範羅蘇姆(龜叔)在1989年開發.python崇尚優美,清晰,簡單. 1.2 python是一門解釋型語言,屬於弱類型語言. 1.3 優點
C#反射 獲取程式集資訊和通過類名建立類例項
C#反射獲取程式集資訊和通過類名建立類例項 。 System.Reflection 名稱空間:包含通過檢查託管程式碼中程式集、模組、成員、引數和其他實體的元資料來檢索其相關資訊的型別。 Assembly 類:表示一個程式集,它是一個可重用、無版本衝突並且可自我描述的公共語言
spring原理案例-基本專案搭建 02 spring jar包詳解 spring jar包的用途
Spring4 Jar包詳解 SpringJava Spring AOP: Spring的面向切面程式設計,提供AOP(面向切面程式設計)的實現 Spring Aspects: Spring提供的對AspectJ框架的整合 Spring Beans: Spring IOC的基礎實現,包含訪問配置
spring-session和redis解決spring cloud中session不一致性問題
現在都比較流行使用spring boot來進行開發,使用spring cloud來搭建分散式。在搭建的時候會涉及到一個關鍵的問題,session統一的問題。使用zuul作為閘道器轉發來呼叫其他模組,zuul中的session和其他模組的session會不一致,同
談談你對hibernate的看法和了解
1,Hibernate是一個開放原始碼的物件關係對映(ORM)框架,它對JDBC進行了非常輕量級的物件封裝,使得程式設計師可以按照面向物件的思想來操控資料庫中的資料 2.hibernate的核心介面有Configuration、SessionFactory 、Session
計算機視覺-計算機視覺入坑(一):計算機視覺入坑前的資訊採集和了解
之前一直覺得自己學的雜而不專,在之後的學習和幹活歷程中也不斷髮現自己確實需要靜下心來鑽研,讓自己像身邊的師兄一樣能有一技之長,能在社會上有自己的立足之地。講真在計算機這個龐大的體系下挑選出一個方向來確實蠻難,自己挑來挑去,有種亂花漸欲迷人眼的感覺,不過就目前自己的興趣、性格和