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;
/**
* 定義基本介面類;
*
* @version v.0.1
* @date 2016年7月25日下午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
* @version v.0.1
* @date 2016年7月25日下午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:412887952;QQ交流群:193341332)
* @version v.0.1
* @date 2016年7月25日下午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:412887952;QQ交流群:193341332)
* @version v.0.1
* @date 2016年7月25日下午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:412887952;QQ交流群:193341332)
* @version v.0.1
* @date 2016年7月25日下午10:23:11
*/
@Service
public class TestServiceImpl extends BaseTestService implements TestService{
}
在執行測試程式碼,完美執行。
第二種方法就是修改Spring Boot的預設動態代理模式,我們剛才說了預設的是Java的動態代理模式,我們只需要修改為CGLIB動態程式碼模式即可,只需要在application.properties加入如下配置:
#開啟CGLIB動態代理模式
spring.aop.proxy-target-class=true
重新執行測試程式碼,也可完美執行。