最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一篇文章帶你了解spring事務(wù)失效的多種場景

 更新時間:2021年09月06日 09:20:28   作者:蘇三說技術(shù)  
在日常編碼過程中常常涉及到事務(wù),在前兩天看到一篇文章提到了Spring事務(wù),那么在此總結(jié)下在Spring環(huán)境下事務(wù)失效的幾種原因.

前言

對于從事java開發(fā)工作的同學(xué)來說,spring的事務(wù)肯定再熟悉不過了。

在某些業(yè)務(wù)場景下,如果一個請求中,需要同時寫入多張表的數(shù)據(jù)。為了保證操作的原子性(要么同時成功,要么同時失?。?,避免數(shù)據(jù)不一致的情況,我們一般都會用到spring事務(wù)。

確實(shí),spring事務(wù)用起來賊爽,就用一個簡單的注解:@Transactional,就能輕松搞定事務(wù)。我猜大部分小伙伴也是這樣用的,而且一直用一直爽。

但如果你使用不當(dāng),它也會坑你于無形。

今天我們就一起聊聊,事務(wù)失效的一些場景,說不定你已經(jīng)中招了。不信,讓我們一起看看。

最近無意間獲得一份BAT大廠大佬寫的刷題筆記,一下子打通了我的任督二脈,越來越覺得算法沒有想象中那么難了。

BAT大佬寫的刷題筆記,讓我offer拿到手軟

一 事務(wù)不生效

1.訪問權(quán)限問題

眾所周知,java的訪問權(quán)限主要有四種:private、default、protected、public,它們的權(quán)限從左到右,依次變大。

但如果我們在開發(fā)過程中,把有某些事務(wù)方法,定義了錯誤的訪問權(quán)限,就會導(dǎo)致事務(wù)功能出問題,例如:

@Service
public class UserService {
    @Transactional
    private void add(UserModel userModel) {
         saveData(userModel);
         updateData(userModel);
    }
}

我們可以看到add方法的訪問權(quán)限被定義成了private,這樣會導(dǎo)致事務(wù)失效,spring要求被代理方法必須是public的。

說白了,在AbstractFallbackTransactionAttributeSource類的computeTransactionAttribute方法中有個判斷,如果目標(biāo)方法不是public,則TransactionAttribute返回null,即不支持事務(wù)。

protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
    // Don't allow no-public methods as required.
    if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
      return null;
    }
    // The method may be on an interface, but we need attributes from the target class.
    // If the target class is null, the method will be unchanged.
    Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
    // First try is the method in the target class.
    TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
    if (txAttr != null) {
      return txAttr;
    }
    // Second try is the transaction attribute on the target class.
    txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
    if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
      return txAttr;
    }
    if (specificMethod != method) {
      // Fallback is to look at the original method.
      txAttr = findTransactionAttribute(method);
      if (txAttr != null) {
        return txAttr;
      }
      // Last fallback is the class of the original method.
      txAttr = findTransactionAttribute(method.getDeclaringClass());
      if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
        return txAttr;
      }
    }
    return null;
  }

也就是說,如果我們自定義的事務(wù)方法(即目標(biāo)方法),它的訪問權(quán)限不是public,而是private、default或protected的話,spring則不會提供事務(wù)功能。

2. 方法用final修飾

有時候,某個方法不想被子類重新,這時可以將該方法定義成final的。普通方法這樣定義是沒問題的,但如果將事務(wù)方法定義成final,例如:

@Service
public class UserService {
    @Transactional
    public final void add(UserModel userModel){
        saveData(userModel);
        updateData(userModel);
    }
}

我們可以看到add方法被定義成了final的,這樣會導(dǎo)致事務(wù)失效。

為什么?

如果你看過spring事務(wù)的源碼,可能會知道spring事務(wù)底層使用了aop,也就是通過jdk動態(tài)代理或者cglib,幫我們生成了代理類,在代理類中實(shí)現(xiàn)的事務(wù)功能。

但如果某個方法用final修飾了,那么在它的代理類中,就無法重寫該方法,而添加事務(wù)功能。

注意:如果某個方法是static的,同樣無法通過動態(tài)代理,變成事務(wù)方法。

3.方法內(nèi)部調(diào)用

有時候我們需要在某個Service類的某個方法中,調(diào)用另外一個事務(wù)方法,比如:

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    @Transactional
    public void add(UserModel userModel) {
        userMapper.insertUser(userModel);
        updateStatus(userModel);
    }
    @Transactional
    public void updateStatus(UserModel userModel) {
        doSameThing();
    }
}

我們看到在事務(wù)方法add中,直接調(diào)用事務(wù)方法updateStatus。從前面介紹的內(nèi)容可以知道,updateStatus方法擁有事務(wù)的能力是因為spring aop生成代理了對象,但是這種方法直接調(diào)用了this對象的方法,所以updateStatus方法不會生成事務(wù)。

由此可見,在同一個類中的方法直接內(nèi)部調(diào)用,會導(dǎo)致事務(wù)失效。

那么問題來了,如果有些場景,確實(shí)想在同一個類的某個方法中,調(diào)用它自己的另外一個方法,該怎么辦呢?

3.1 新加一個Service方法

這個方法非常簡單,只需要新加一個Service方法,把@Transactional注解加到新Service方法上,把需要事務(wù)執(zhí)行的代碼移到新方法中。具體代碼如下:

@Servcie
public class ServiceA {
   @Autowired
   prvate ServiceB serviceB;
   public void save(User user) {
         queryData1();
         queryData2();
         serviceB.doSave(user);
   }
 }
 @Servcie
 public class ServiceB {
    @Transactional(rollbackFor=Exception.class)
    public void doSave(User user) {
       addData1();
       updateData2();
    }
 }

3.2 在該Service類中注入自己

如果不想再新加一個Service類,在該Service類中注入自己也是一種選擇。具體代碼如下:

@Servcie
public class ServiceA {
   @Autowired
   prvate ServiceA serviceA;
   public void save(User user) {
         queryData1();
         queryData2();
         serviceA.doSave(user);
   }
   @Transactional(rollbackFor=Exception.class)
   public void doSave(User user) {
       addData1();
       updateData2();
    }
 }

可能有些人可能會有這樣的疑問:這種做法會不會出現(xiàn)循環(huán)依賴問題?

答案:不會。

3.3 通過AopContent類

在該Service類中使用AopContext.currentProxy()獲取代理對象

上面的方法2確實(shí)可以解決問題,但是代碼看起來并不直觀,還可以通過在該Service類中使用AOPProxy獲取代理對象,實(shí)現(xiàn)相同的功能。具體代碼如下:

@Servcie
public class ServiceA {
   public void save(User user) {
         queryData1();
         queryData2();
         ((ServiceA)AopContext.currentProxy()).doSave(user);
   }
   @Transactional(rollbackFor=Exception.class)
   public void doSave(User user) {
       addData1();
       updateData2();
    }
 }

4.未被spring管理

在我們平時開發(fā)過程中,有個細(xì)節(jié)很容易被忽略。即使用spring事務(wù)的前提是:對象要被spring管理,需要創(chuàng)建bean實(shí)例。

通常情況下,我們通過@Controller、@Service、@Component、@Repository等注解,可以自動實(shí)現(xiàn)bean實(shí)例化和依賴注入的功能。

當(dāng)然創(chuàng)建bean實(shí)例的方法還有很多,有興趣的小伙伴可以看看我之前寫的另一篇文章《@Autowired的這些騷操作,你都知道嗎?》

如果有一天,你匆匆忙忙的開發(fā)了一個Service類,但忘了加@Service注解,比如:

//@Service
public class UserService {
    @Transactional
    public void add(UserModel userModel) {
         saveData(userModel);
         updateData(userModel);
    }    
}

從上面的例子,我們可以看到UserService類沒有加@Service注解,那么該類不會交給spring管理,所以它的add方法也不會生成事務(wù)。

5.多線程調(diào)用

在實(shí)際項目開發(fā)中,多線程的使用場景還是挺多的。如果spring事務(wù)用在多線程場景中,會有問題嗎?

@Slf4j
@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RoleService roleService;
    @Transactional
    public void add(UserModel userModel) throws Exception {
        userMapper.insertUser(userModel);
        new Thread(() -> {
            roleService.doOtherThing();
        }).start();
    }
}
@Service
public class RoleService {
    @Transactional
    public void doOtherThing() {
        System.out.println("保存role表數(shù)據(jù)");
    }
}

從上面的例子中,我們可以看到事務(wù)方法add中,調(diào)用了事務(wù)方法doOtherThing,但是事務(wù)方法doOtherThing是在另外一個線程中調(diào)用的。

這樣會導(dǎo)致兩個方法不在同一個線程中,獲取到的數(shù)據(jù)庫連接不一樣,從而是兩個不同的事務(wù)。如果想doOtherThing方法中拋了異常,add方法也回滾是不可能的。

如果看過spring事務(wù)源碼的朋友,可能會知道spring的事務(wù)是通過數(shù)據(jù)庫連接來實(shí)現(xiàn)的。當(dāng)前線程中保存了一個map,key是數(shù)據(jù)源,value是數(shù)據(jù)庫連接。

private static final ThreadLocal<Map<Object, Object>> resources =
  new NamedThreadLocal<>("Transactional resources");

我們說的同一個事務(wù),其實(shí)是指同一個數(shù)據(jù)庫連接,只有擁有同一個數(shù)據(jù)庫連接才能同時提交和回滾。如果在不同的線程,拿到的數(shù)據(jù)庫連接肯定是不一樣的,所以是不同的事務(wù)。

6.表不支持事務(wù)

周所周知,在mysql5之前,默認(rèn)的數(shù)據(jù)庫引擎是myisam。

它的好處就不用多說了:索引文件和數(shù)據(jù)文件是分開存儲的,對于查多寫少的單表操作,性能比innodb更好。

有些老項目中,可能還在用它。

在創(chuàng)建表的時候,只需要把ENGINE參數(shù)設(shè)置成MyISAM即可:

CREATE TABLE `category` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `one_category` varchar(20) COLLATE utf8mb4_bin DEFAULT NULL,
  `two_category` varchar(20) COLLATE utf8mb4_bin DEFAULT NULL,
  `three_category` varchar(20) COLLATE utf8mb4_bin DEFAULT NULL,
  `four_category` varchar(20) COLLATE utf8mb4_bin DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin

myisam好用,但有個很致命的問題是:不支持事務(wù)。

如果只是單表操作還好,不會出現(xiàn)太大的問題。但如果需要跨多張表操作,由于其不支持事務(wù),數(shù)據(jù)極有可能會出現(xiàn)不完整的情況。

此外,myisam還不支持行鎖和外鍵。

所以在實(shí)際業(yè)務(wù)場景中,myisam使用的并不多。在mysql5以后,myisam已經(jīng)逐漸退出了歷史的舞臺,取而代之的是innodb。

有時候我們在開發(fā)的過程中,發(fā)現(xiàn)某張表的事務(wù)一直都沒有生效,那不一定是spring事務(wù)的鍋,最好確認(rèn)一下你使用的那張表,是否支持事務(wù)。

7.未開啟事務(wù)

有時候,事務(wù)沒有生效的根本原因是沒有開啟事務(wù)。

你看到這句話可能會覺得好笑。

開啟事務(wù)不是一個項目中,最最最基本的功能嗎?

為什么還會沒有開啟事務(wù)?

沒錯,如果項目已經(jīng)搭建好了,事務(wù)功能肯定是有的。

但如果你是在搭建項目demo的時候,只有一張表,而這張表的事務(wù)沒有生效。那么會是什么原因造成的呢?

當(dāng)然原因有很多,但沒有開啟事務(wù),這個原因極其容易被忽略。

如果你使用的是springboot項目,那么你很幸運(yùn)。因為springboot通過DataSourceTransactionManagerAutoConfiguration類,已經(jīng)默默的幫你開啟了事務(wù)。

你所要做的事情很簡單,只需要配置spring.datasource相關(guān)參數(shù)即可。

但如果你使用的還是傳統(tǒng)的spring項目,則需要在applicationContext.xml文件中,手動配置事務(wù)相關(guān)參數(shù)。如果忘了配置,事務(wù)肯定是不會生效的。

具體配置如下信息:

<!-- 配置事務(wù)管理器 --> 
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager"> 
    <property name="dataSource" ref="dataSource"></property> 
</bean> 
<tx:advice id="advice" transaction-manager="transactionManager"> 
    <tx:attributes> 
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes> 
</tx:advice> 
<!-- 用切點(diǎn)把事務(wù)切進(jìn)去 --> 
<aop:config> 
    <aop:pointcut expression="execution(* com.susan.*.*(..))" id="pointcut"/> 
    <aop:advisor advice-ref="advice" pointcut-ref="pointcut"/> 
</aop:config> 

默默的說一句,如果在pointcut標(biāo)簽中的切入點(diǎn)匹配規(guī)則,配錯了的話,有些類的事務(wù)也不會生效。

二 事務(wù)不回滾

1.錯誤的傳播特性

其實(shí),我們在使用@Transactional注解時,是可以指定propagation參數(shù)的。

該參數(shù)的作用是指定事務(wù)的傳播特性,spring目前支持7種傳播特性:

  • REQUIRED 如果當(dāng)前上下文中存在事務(wù),那么加入該事務(wù),如果不存在事務(wù),創(chuàng)建一個事務(wù),這是默認(rèn)的傳播屬性值。
  • SUPPORTS 如果當(dāng)前上下文存在事務(wù),則支持事務(wù)加入事務(wù),如果不存在事務(wù),則使用非事務(wù)的方式執(zhí)行。
  • MANDATORY 如果當(dāng)前上下文中存在事務(wù),否則拋出異常。
  • REQUIRES_NEW 每次都會新建一個事務(wù),并且同時將上下文中的事務(wù)掛起,執(zhí)行當(dāng)前新建事務(wù)完成以后,上下文事務(wù)恢復(fù)再執(zhí)行。
  • NOT_SUPPORTED 如果當(dāng)前上下文中存在事務(wù),則掛起當(dāng)前事務(wù),然后新的方法在沒有事務(wù)的環(huán)境中執(zhí)行。
  • NEVER 如果當(dāng)前上下文中存在事務(wù),則拋出異常,否則在無事務(wù)環(huán)境上執(zhí)行代碼。
  • NESTED 如果當(dāng)前上下文中存在事務(wù),則嵌套事務(wù)執(zhí)行,如果不存在事務(wù),則新建事務(wù)。

如果我們在手動設(shè)置propagation參數(shù)的時候,把傳播特性設(shè)置錯了,比如:

@Service
public class UserService {
    @Transactional(propagation = Propagation.NEVER)
    public void add(UserModel userModel) {
        saveData(userModel);
        updateData(userModel);
    }
}

我們可以看到add方法的事務(wù)傳播特性定義成了Propagation.NEVER,這種類型的傳播特性不支持事務(wù),如果有事務(wù)則會拋異常。

目前只有這三種傳播特性才會創(chuàng)建新事務(wù):REQUIRED,REQUIRES_NEW,NESTED。

2.自己吞了異常

事務(wù)不會回滾,最常見的問題是:開發(fā)者在代碼中手動try…catch了異常。比如:

@Slf4j
@Service
public class UserService {
    @Transactional
    public void add(UserModel userModel) {
        try {
            saveData(userModel);
            updateData(userModel);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }
}

這種情況下spring事務(wù)當(dāng)然不會回滾,因為開發(fā)者自己捕獲了異常,又沒有手動拋出,換句話說就是把異常吞掉了。

如果想要spring事務(wù)能夠正?;貪L,必須拋出它能夠處理的異常。如果沒有拋異常,則spring認(rèn)為程序是正常的。

3.手動拋了別的異常

即使開發(fā)者沒有手動捕獲異常,但如果拋的異常不正確,spring事務(wù)也不會回滾。

@Slf4j
@Service
public class UserService {
    @Transactional
    public void add(UserModel userModel) throws Exception {
        try {
             saveData(userModel);
             updateData(userModel);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new Exception(e);
        }
    }
}

上面的這種情況,開發(fā)人員自己捕獲了異常,又手動拋出了異常:Exception,事務(wù)同樣不會回滾。

因為spring事務(wù),默認(rèn)情況下只會回滾RuntimeException(運(yùn)行時異常)和Error(錯誤),對于普通的Exception(非運(yùn)行時異常),它不會回滾。

4.自定義了回滾異常

在使用@Transactional注解聲明事務(wù)時,有時我們想自定義回滾的異常,spring也是支持的??梢酝ㄟ^設(shè)置rollbackFor參數(shù),來完成這個功能。

但如果這個參數(shù)的值設(shè)置錯了,就會引出一些莫名其妙的問題,例如:

@Slf4j
@Service
public class UserService {
    @Transactional(rollbackFor = BusinessException.class)
    public void add(UserModel userModel) throws Exception {
       saveData(userModel);
       updateData(userModel);
    }
}

如果在執(zhí)行上面這段代碼,保存和更新數(shù)據(jù)時,程序報錯了,拋了SqlException、DuplicateKeyException等異常。而BusinessException是我們自定義的異常,報錯的異常不屬于BusinessException,所以事務(wù)也不會回滾。

即使rollbackFor有默認(rèn)值,但阿里巴巴開發(fā)者規(guī)范中,還是要求開發(fā)者重新指定該參數(shù)。

這是為什么呢?

因為如果使用默認(rèn)值,一旦程序拋出了Exception,事務(wù)不會回滾,這會出現(xiàn)很大的bug。所以,建議一般情況下,將該參數(shù)設(shè)置成:Exception或Throwable。

5.嵌套事務(wù)回滾多了

public class UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RoleService roleService;
    @Transactional
    public void add(UserModel userModel) throws Exception {
        userMapper.insertUser(userModel);
        roleService.doOtherThing();
    }
}
@Service
public class RoleService {
    @Transactional(propagation = Propagation.NESTED)
    public void doOtherThing() {
        System.out.println("保存role表數(shù)據(jù)");
    }
}

這種情況使用了嵌套的內(nèi)部事務(wù),原本是希望調(diào)用roleService.doOtherThing方法時,如果出現(xiàn)了異常,只回滾doOtherThing方法里的內(nèi)容,不回滾 userMapper.insertUser里的內(nèi)容,即回滾保存點(diǎn)。。但事實(shí)是,insertUser也回滾了。

why?

因為doOtherThing方法出現(xiàn)了異常,沒有手動捕獲,會繼續(xù)往上拋,到外層add方法的代理方法中捕獲了異常。所以,這種情況是直接回滾了整個事務(wù),不只回滾單個保存點(diǎn)。

怎么樣才能只回滾保存點(diǎn)呢?

@Slf4j
@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RoleService roleService;
    @Transactional
    public void add(UserModel userModel) throws Exception {
        userMapper.insertUser(userModel);
        try {
            roleService.doOtherThing();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }
}

可以將內(nèi)部嵌套事務(wù)放在try/catch中,并且不繼續(xù)往上拋異常。這樣就能保證,如果內(nèi)部嵌套事務(wù)中出現(xiàn)異常,只回滾內(nèi)部事務(wù),而不影響外部事務(wù)。

三 其他

1 大事務(wù)問題

在使用spring事務(wù)時,有個讓人非常頭疼的問題,就是大事務(wù)問題。

通常情況下,我們會在方法上@Transactional注解,填加事務(wù)功能,比如:

@Service
public class UserService {
    @Autowired 
    private RoleService roleService;
    @Transactional
    public void add(UserModel userModel) throws Exception {
       query1();
       query2();
       query3();
       roleService.save(userModel);
       update(userModel);
    }
}

@Service
public class RoleService {
    @Autowired 
    private RoleService roleService;
    @Transactional
    public void save(UserModel userModel) throws Exception {
       query4();
       query5();
       query6();
       saveData(userModel);
    }
}

@Transactional注解,如果被加到方法上,有個缺點(diǎn)就是整個方法都包含在事務(wù)當(dāng)中了。

上面的這個例子中,在UserService類中,其實(shí)只有這兩行才需要事務(wù):

roleService.save(userModel);
update(userModel);

在RoleService類中,只有這一行需要事務(wù):

saveData(userModel);

現(xiàn)在的這種寫法,會導(dǎo)致所有的query方法也被包含在同一個事務(wù)當(dāng)中。

如果query方法非常多,調(diào)用層級很深,而且有部分查詢方法比較耗時的話,會造成整個事務(wù)非常耗時,而從造成大事務(wù)問題。

關(guān)于大事務(wù)問題的危害,可以閱讀一下我的另一篇文章《讓人頭痛的大事務(wù)問題到底要如何解決?》,上面有詳細(xì)的講解。


2.編程式事務(wù)

上面聊的這些內(nèi)容都是基于@Transactional注解的,主要說的是它的事務(wù)問題,我們把這種事務(wù)叫做:聲明式事務(wù)。

其實(shí),spring還提供了另外一種創(chuàng)建事務(wù)的方式,即通過手動編寫代碼實(shí)現(xiàn)的事務(wù),我們把這種事務(wù)叫做:編程式事務(wù)。例如:

   @Autowired
   private TransactionTemplate transactionTemplate;
   ...
   public void save(final User user) {
         queryData1();
         queryData2();
         transactionTemplate.execute((status) => {
            addData1();
            updateData2();
            return Boolean.TRUE;
         })
   }

在spring中為了支持編程式事務(wù),專門提供了一個類:TransactionTemplate,在它的execute方法中,就實(shí)現(xiàn)了事務(wù)的功能。

相較于@Transactional注解聲明式事務(wù),我更建議大家使用,基于TransactionTemplate的編程式事務(wù)。主要原因如下:

避免由于spring aop問題,導(dǎo)致事務(wù)失效的問題。能夠更小粒度的控制事務(wù)的范圍,更直觀。

建議在項目中少使用@Transactional注解開啟事務(wù)。但并不是說一定不能用它,如果項目中有些業(yè)務(wù)邏輯比較簡單,而且不經(jīng)常變動,使用@Transactional注解開啟事務(wù)開啟事務(wù)也無妨,因為它更簡單,開發(fā)效率更高,但是千萬要小心事務(wù)失效的問題。

總結(jié)

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • Java中的maven和gradle的比較與使用詳解

    Java中的maven和gradle的比較與使用詳解

    這篇文章主要介紹了maven和gradle的比較與使用,Maven使用基于XML的配置,Gradle采用了領(lǐng)域特定語言Groovy的配置,在Maven中要引入一個依賴,需要的朋友可以參考下
    2022-04-04
  • Java swing實(shí)現(xiàn)的計算器功能完整實(shí)例

    Java swing實(shí)現(xiàn)的計算器功能完整實(shí)例

    這篇文章主要介紹了Java swing實(shí)現(xiàn)的計算器功能,結(jié)合完整實(shí)例形式分析了java基于swing組件實(shí)現(xiàn)計算器布局與運(yùn)算功能的具體操作技巧,需要的朋友可以參考下
    2017-12-12
  • java_IO向文件中寫入和讀取內(nèi)容代碼實(shí)例

    java_IO向文件中寫入和讀取內(nèi)容代碼實(shí)例

    這篇文章主要介紹了java_IO向文件中寫入和讀取內(nèi)容,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • 關(guān)于ThreadLocal的用法和說明及注意事項

    關(guān)于ThreadLocal的用法和說明及注意事項

    這篇文章主要介紹了關(guān)于ThreadLocal的用法和說明及注意事項,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • Spring如何正確注入集合類型

    Spring如何正確注入集合類型

    這篇文章主要介紹了Spring如何正確注入集合類型,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09
  • Java中的CopyOnWriteArrayList原理詳解

    Java中的CopyOnWriteArrayList原理詳解

    這篇文章主要介紹了Java中的CopyOnWriteArrayList原理詳解,如源碼所示,CopyOnWriteArrayList和ArrayList一樣,都在內(nèi)部維護(hù)了一個數(shù)組,操作CopyOnWriteArrayList其實(shí)就是在操作內(nèi)部的數(shù)組,需要的朋友可以參考下
    2023-12-12
  • Springboot 自定義校驗代碼實(shí)例

    Springboot 自定義校驗代碼實(shí)例

    這篇文章主要介紹了Springboot 自定義校驗代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • Java中默認(rèn)的訪問權(quán)限作用域解析

    Java中默認(rèn)的訪問權(quán)限作用域解析

    這篇文章主要介紹了Java中默認(rèn)的訪問權(quán)限作用域,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java 獲取服務(wù)器環(huán)境的實(shí)例詳解

    Java 獲取服務(wù)器環(huán)境的實(shí)例詳解

    這篇文章主要介紹了Java 獲取服務(wù)器環(huán)境的實(shí)例詳解的相關(guān)資料,這里提供實(shí)例和輸出結(jié)果,希望能幫助大家理解,需要的朋友可以參考下
    2017-07-07
  • Mybatis攔截器實(shí)現(xiàn)數(shù)據(jù)分表

    Mybatis攔截器實(shí)現(xiàn)數(shù)據(jù)分表

    當(dāng)數(shù)據(jù)量比較多時,放在一個表中的時候會影響查詢效率,本文主要介紹了Mybatis攔截器實(shí)現(xiàn)數(shù)據(jù)分表,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-01-01

最新評論

金湖县| 墨江| 小金县| 万盛区| 法库县| 永嘉县| 互助| 乐亭县| 榆树市| 浦江县| 云霄县| 弋阳县| 湖州市| 阜阳市| 新化县| 洱源县| 马山县| 安福县| 闵行区| 萨嘎县| 临武县| 汝阳县| 榆树市| 梓潼县| 长汀县| 景洪市| 江北区| 尚义县| 潼南县| 泰宁县| 西贡区| 津市市| 林甸县| 定西市| 临朐县| 任丘市| 威信县| 漠河县| 万安县| 泽库县| 赤峰市|