[记录]Spring注入的对象类型

2018-07-03  本文已影响0人  beldon_wu

开篇

之前,在用spring编码调试的时候,有时候发现被自动注入的对象是原始类的对象,有时候是代理类的对象,那什么时候注入的原始类对象呢,有什么时候注入的是代理类的对象呢?心里就留下了这个疑问。后来再次看spring aop的时候变有了大胆的想法。

案例

先添加springboot依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>2.0.2.RELEASE</version>
</dependency>
添加测试的类
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 {
}

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());
    }
}
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());
    }
}
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);
    }
}
代码描述
运行结果
------------
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

结果可以看出DemoService是被注入的是原始类的对象,Demo2Service被注入的对象是jdk代理的对象,Demo3Service被注入的对象是cglib的代理对象

将注入的demo2Service改为实现类注入
@Autowired
private Demo2ServiceImpl demo2Service;

运行结果如下:

***************************
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是实现Demo2Service接口的一个jdk动态代理,不能直接被注入

强制使用cglib

修改CheckApplication中的@EnableAsync如下

@EnableAsync(proxyTargetClass = true)

运行结果如下:

------------
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

上面结果是Demo2ServiceDemo3Service被注入的都是cglib代理类

结论

spring很多功能都是通过aop来实现,如果事务,缓存注解,异步、还有一些自定义的aop等等,而aop是通过动态代理来实现的,spring主要用到的动态代理有jdk的动态代理和cglib。

上一篇下一篇

猜你喜欢

热点阅读