1. 程式人生 > >67. @Transactional的類注入失敗【從零開始學Spring Boot】

67. @Transactional的類注入失敗【從零開始學Spring Boot】

【從零開始學習Spirng Boot—常見異常彙總】

       Spring的代理模式有兩種:java自帶的動態代理模式和cglib代理模式,cglib程式碼模式適用於沒有介面的類,而java自帶適用於介面類,預設情況下spring boot或者spring 採用介面類的代理模式,如果我們是基於介面程式設計的,是不會發生問題的,但是如果我們定義了一個class類繼承Base類的時候就會出問題了。如下程式碼就會出現問題:

基本介面類com.kfit.demo.test.IBaseTestService:

package com.kfit.demo.test;

/**

 * 定義基本介面類;

 * 

@author Angel(QQ:412887952QQ交流群:193341332)

 * @version v.0.1

 * @date 2016725下午10:20:45

 */

public interface IBaseTestService {

    public void sayHello();

}

基本介面實現com.kfit.demo.test.BaseTestService:

package com.kfit.demo.test;

import javax.transaction.Transactional;

/**

 * 基本介面實現

 * @author Angel(QQ:412887952

QQ交流群:193341332)

 * @version v.0.1

 * @date 2016725下午10:21:41

 */

public class BaseTestService implements IBaseTestService{

    @Transactional

    public void sayHello() {

       System.out.println("BaseTestService.sayHello()");

    }

}

測試服務類com.kfit.demo.test.TestService:

package com.kfit.demo.test;

import org.springframework.stereotype.Service;

/**

 * 測試類;

 * @author Angel(QQ:412887952QQ交流群:193341332)

 * @version v.0.1

 * @date 2016725下午10:23:11

 */

@Service

public class TestService extends BaseTestService{

}

測試類引用:

@Autowired

private TestService testService;

呼叫:testService.sayHello();

執行以上我們編寫的程式碼,是會丟擲異常的,無法找到TestService 實體類。

       那麼這個就是由於Spring Boot預設使用了Java自帶的動態代理模式(介面代理)。

我們要怎麼修改呢?有兩種方案遵循介面模式程式設計:

第一種方案:將上面的TestService修改為介面,然後新增一個TestService的實現類。程式碼如下:

com.kfit.demo.test.TestService 修改為介面,程式碼如下:

package com.kfit.demo.test;

/**

 * 測試類;

 * @author Angel(QQ:412887952QQ交流群:193341332)

 * @version v.0.1

 * @date 2016725下午10:23:11

 */

public interface TestService extends IBaseTestService{

}

TestService介面的實現類com.kfit.demo.test.TestServiceImpl:

package com.kfit.demo.test;

import org.springframework.stereotype.Service;

/**

 * 測試類;

 * @author Angel(QQ:412887952QQ交流群:193341332)

 * @version v.0.1

 * @date 2016725下午10:23:11

 */

@Service

public class TestServiceImpl extends BaseTestService implements TestService{

}

在執行測試程式碼,完美執行。

第二種方法就是修改Spring Boot的預設動態代理模式,我們剛才說了預設的是Java的動態代理模式,我們只需要修改為CGLIB動態程式碼模式即可,只需要在application.properties加入如下配置:

#開啟CGLIB動態代理模式

spring.aop.proxy-target-class=true

重新執行測試程式碼,也可完美執行。