[記錄]Spring注入的對象類型

開篇

之前,在用spring編碼調(diào)試的時候,有時候發(fā)現(xiàn)被自動注入的對象是原始類的對象,有時候是代理類的對象,那什么時候注入的原始類對象呢,有什么時候注入的是代理類的對象呢?心里就留下了這個疑問。后來再次看spring aop的時候變有了大膽的想法。

案例

先添加springboot依賴
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>2.0.2.RELEASE</version>
</dependency>
添加測試的類
  • 添加Service1
package beldon.service;
public interface DemoService {
}
package beldon.service.impl;
import beldon.service.DemoService;
import org.springframework.stereotype.Service;
@Service
public class DemoServiceImpl implements DemoService {
}

  • 添加Service2
package beldon.service;
public interface Demo2Service {
    void asyncDemo();
}
package beldon.service.impl;
import beldon.service.Demo2Service;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class Demo2ServiceImpl implements Demo2Service {
    @Override
    @Async
    public void asyncDemo() {
        System.out.println("Demo2Service:" + Thread.currentThread().getName());
    }
}
  • 添加Service3
package beldon.service.impl;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class Demo3Service {
    @Async
    public void asyncDemo() {
        System.out.println("Demo3Service:" + Thread.currentThread().getName());
    }
}
  • Application
package beldon.proxycheck;
import beldon.service.Demo2Service;
import beldon.service.DemoService;
import beldon.service.impl.Demo3Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import javax.annotation.PostConstruct;

@SpringBootApplication
@EnableAsync
public class CheckApplication {
    @Autowired
    private DemoService demoService;
    @Autowired
    private Demo2Service demo2Service;
    @Autowired
    private Demo3Service demo3Service;
    @PostConstruct
    public void init() {
        System.out.println("------------");
        System.out.println("DemoService:"+demoService.getClass().getName());
        System.out.println("Demo2Service:"+demo2Service.getClass().getName());
        System.out.println("Demo3Service:"+demo3Service.getClass().getName());
        System.out.println("------------");
        demo2Service.asyncDemo();
        demo3Service.asyncDemo();
        System.out.println("CheckApplication:"+Thread.currentThread().getName());
    }
    public static void main(String[] args) {
        SpringApplication.run(CheckApplication.class);
    }
}
代碼描述
  • 添加了3個service,DemoService、Demo2Service是接口,有實現(xiàn)類。Demo3Service是沒有接口,只有單一的類
  • Demo2ServiceDemo3ServiceasyncDemo()方法上有@Async注解
  • CheckApplication方法上有@EnableAsync,用來開啟異步
運行結(jié)果
------------
DemoService:beldon.proxycheck.service.impl.DemoServiceImpl
Demo2Service:com.sun.proxy.$Proxy37
Demo3Service:beldon.proxycheck.service.impl.Demo3Service$$EnhancerBySpringCGLIB$$b4ca4e7c
------------
Demo2Service:SimpleAsyncTaskExecutor-1
CheckApplication:main
Demo3Service:SimpleAsyncTaskExecutor-2

結(jié)果可以看出DemoService是被注入的是原始類的對象,Demo2Service被注入的對象是jdk代理的對象,Demo3Service被注入的對象是cglib的代理對象

將注入的demo2Service改為實現(xiàn)類注入
@Autowired
private Demo2ServiceImpl demo2Service;

運行結(jié)果如下:

***************************
APPLICATION FAILED TO START
***************************

Description:

The bean 'demo2ServiceImpl' could not be injected as a 'beldon.service.impl.Demo2ServiceImpl' because it is a JDK dynamic proxy that implements:
    beldon.service.Demo2Service

Action:

Consider injecting the bean as one of its interfaces or forcing the use of CGLib-based proxies by setting proxyTargetClass=true on @EnableAsync and/or @EnableCaching.

上面錯誤描述的是demo2ServiceImpl是實現(xiàn)Demo2Service接口的一個jdk動態(tài)代理,不能直接被注入

強制使用cglib

修改CheckApplication中的@EnableAsync如下

@EnableAsync(proxyTargetClass = true)

運行結(jié)果如下:

------------
DemoService:beldon.proxycheck.service.impl.DemoServiceImpl
Demo2Service:beldon.proxycheck.service.impl.Demo2ServiceImpl$$EnhancerBySpringCGLIB$$c39af2f2
Demo3Service:beldon.proxycheck.service.impl.Demo3Service$$EnhancerBySpringCGLIB$$b074e2af
CheckApplication:main
Demo2Service:SimpleAsyncTaskExecutor-1
Demo3Service:SimpleAsyncTaskExecutor-2

上面結(jié)果是Demo2Service、Demo3Service被注入的都是cglib代理類

結(jié)論

spring很多功能都是通過aop來實現(xiàn),如果事務(wù),緩存注解,異步、還有一些自定義的aop等等,而aop是通過動態(tài)代理來實現(xiàn)的,spring主要用到的動態(tài)代理有jdk的動態(tài)代理和cglib。

  • Spring 在沒有使用aop的時候自動注入的時候是原始類型對象
  • 在發(fā)生aop的時候,若代理對象有實現(xiàn)接口,則默認(rèn)會使用jdk動態(tài)代理
  • 在發(fā)生aop的時候,若代理對象沒有實現(xiàn)接口,則默認(rèn)會使用cglib動態(tài)代理
  • jdk動態(tài)代理必須有實現(xiàn)接口
  • 可以強制使用cglib來做spring動態(tài)代理
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,597評論 19 139
  • 1.1 spring IoC容器和beans的簡介 Spring 框架的最核心基礎(chǔ)的功能是IoC(控制反轉(zhuǎn))容器,...
    simoscode閱讀 6,851評論 2 22
  • IOC和DI是什么? Spring IOC 的理解,其初始化過程? BeanFactory 和 FactoryBe...
    justlpf閱讀 3,595評論 1 21
  • 什么是Spring Spring是一個開源的Java EE開發(fā)框架。Spring框架的核心功能可以應(yīng)用在任何Jav...
    jemmm閱讀 16,779評論 1 133
  • 吳蕙蘭閱讀 263評論 0 0

友情鏈接更多精彩內(nèi)容