转载

Spring源码系列:依赖注入-引言

在上面四篇文章中大概分析了一下Bean的载入,其实这个过程就是在Ioc容器中建立BeanDefinition的数据映射。但是对于Bean的实例化并未涉及,在之前的分析中也提到,bean的实例化是在依赖注入是才具体完成。

关于依赖注入

关于Spring,我们最先想到的就两个Ioc和Aop;然后关于Ioc我们又能牵扯出两个:控制反转和依赖注入。 控制反转和依赖注入在网上被无数大神亦或菜鸟解读过,这里就不罗列那些概念了,直接看:

不使用Spring

public class UserService {
    //手动new一个
    UserDao userDao = new UserDaoImpl();
    public int insertUser(String userName) {
    	return userDao.insertUser(userName);
    }
}

使用Spring(以注解方式)

public class UserService {
    @Autowired
    private UserDao userDao;
    public int insertUser(String userName) {
    	return userDao.insertUser(userName);
    }
}

看起来貌似没有啥很大的改变,区别呢?

我们先来分析下在一个类中这两种申明的区别:

UserDao userDao;

userDao是UserDao类型的引用名称。仅仅是声明了一个变量引用名称。并没有做实例化,userDao的实例化可以通过set方法进行设置(Spring中之前常用的就是set方法注入);当我们初始化持有userDao的这个类时我们还不知道userDao到底具体指向哪个堆中的对象地址。

UserDao userDao = new UserDaoImpl();

而这个,申明一个变量名称,并将userDao直接指向new UserDaoImpl()创建的对象。

我们来看Spring中关于注入之后对象地址以及不使用注入方式对象的地址:

1、直接注入

Spring源码系列:依赖注入-引言
2、注入覆盖了我自己的对象
Spring源码系列:依赖注入-引言
3、自己手动new
Spring源码系列:依赖注入-引言

通过上面三幅图可以明显的看出,自己手动new的对象没有使用代理的方式,而托管给Spring注入的对象均是通过动态代理来完成的。

关于动态代理: 《猪弟拱Java》连载番外篇:Java代理(中)

总结:当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,在未使用Spring来管理Bean的程序设计过程中,通常由调用者来创建被调用者的实例。但在Spring里,创建被调用者的工作不再由调用者来完成,因此称为控制反转;创建被调用者实例的工作通常由Spring容器来完成,然后注入调用者,因此也称为依赖注入。

三个问题

那么现在要考虑问题就是, 什么时候会触发我们的依赖注入呢?Bean的实例化是否必须在依赖注入时才能完成呢?在Spring中又是通过哪些类来完成注入工作的呢?

1、什么时候会触发我们的依赖注入

答:用户第一次向容器获取Bean的时候出发。

2、Bean的实例化是否必须在依赖注入时才能完成

这个其实不是必须的,咱们都知道BeanDefinition中有lazy-init这样一个属性,我们可以通过控制这个属性的设置来让容器完成对Bean的预实例化。预实例化就是说它的依赖注入是在实例化过程中完成的。

第一和第二个问题将会在分析第三个问题的时候慢慢的细化分析。所以第三个问题其实没啥鸟用,但也是最最最核心的,就是为了引出后面关于一些具体类的分析的。

原文  https://juejin.im/post/5a751c7ef265da4e9673ca40
正文到此结束
Loading...