在Spring根底 - Spring简略例子引入Spring的外围中向你展现了IoC的根底含意,同时以此发散了一些IoC相干知识点; 本节将在此基础上进一步解读IOC的含意以及IOC的应用形式。@pdai
  • Spring框架系列(3) - 深入浅出Spring外围之管制反转(IOC)

    • 引入
    • 如何了解IoC

      • Spring Bean是什么
      • IoC是什么
      • IoC能做什么
      • IoC和DI是什么关系
    • Ioc 配置的三种形式

      • xml 配置
      • Java 配置
      • 注解配置
    • 依赖注入的三种形式

      • setter形式
      • 构造函数
      • 注解注入
    • IoC和DI应用问题小结

      • 为什么举荐结构器注入形式?
      • 我在应用结构器注入形式时注入了太多的类导致Bad Smell怎么办?
      • @Autowired和@Resource以及@Inject等注解注入有何区别?

        • @Autowired
        • @Resource
        • @Inject
        • 总结
    • 参考文章
    • 更多文章

引入

咱们在Spring根底 - Spring简略例子引入Spring的外围中向你展现了IoC的根底含意,同时以此发散了一些IoC相干知识点。
  1. Spring框架治理这些Bean的创立工作,即由用户治理Bean转变为框架治理Bean,这个就叫管制反转 - Inversion of Control (IoC)
  2. Spring 框架托管创立的Bean放在哪里呢? 这便是IoC Container;
  3. Spring 框架为了更好让用户配置Bean,必然会引入不同形式来配置Bean? 这便是xml配置,Java配置,注解配置等反对
  4. Spring 框架既然接管了Bean的生成,必然须要治理整个Bean的生命周期等;
  5. 利用程序代码从Ioc Container中获取依赖的Bean,注入到应用程序中,这个过程叫 依赖注入(Dependency Injection,DI) ; 所以说管制反转是通过依赖注入实现的,其实它们是同一个概念的不同角度形容。艰深来说就是IoC是设计思维,DI是实现形式
  6. 在依赖注入时,有哪些形式呢?这就是结构器形式,@Autowired, @Resource, @Qualifier... 同时Bean之间存在依赖(可能存在先后顺序问题,以及循环依赖问题等)

本节将在此基础上进一步解读IOC的含意以及IOC的应用形式;后续的文章还将深刻IOC的实现原理:

  • Spring进阶- Spring IOC实现原理详解之IOC体系结构设计
  • Spring进阶- Spring IOC实现原理详解之IOC初始化流程
  • Spring进阶- Spring IOC实现原理详解之Bean的注入和生命周期

如何了解IoC

如果你有精力看英文,首推 Martin Fowler巨匠的 Inversion of Control Containers and the Dependency Injection pattern;其次IoC作为一种设计思维,不要适度解读,而是应该简化了解,所以我这里也整合了 张开涛早前的博客IoC根底并退出了本人的了解。

Spring Bean是什么

IoC Container治理的是Spring Bean, 那么Spring Bean是什么呢?

Spring外面的bean就相似是定义的一个组件,而这个组件的作用就是实现某个性能的,这里所定义的bean就相当于给了你一个更为简便的办法来调用这个组件去实现你要实现的性能。

IoC是什么

Ioc—Inversion of Control,即“管制反转”,不是什么技术,而是一种设计思维。在Java开发中,Ioc意味着将你设计好的对象交给容器管制,而不是传统的在你的对象外部间接管制。

咱们来深入分析一下:

  • 谁管制谁,管制什么

传统Java SE程序设计,咱们间接在对象外部通过new进行创建对象,是程序被动去创立依赖对象;而IoC是有专门一个容器来创立这些对象,即由Ioc容器来管制对 象的创立;谁管制谁?当然是IoC 容器管制了对象;管制什么?那就是次要管制了内部资源获取(不只是对象包含比方文件等)。

  • 为何是反转,哪些方面反转了?

有反转就有正转,传统应用程序是由咱们本人在对象中被动管制去间接获取依赖对象,也就是正转;而反转则是由容器来帮忙创立及注入依赖对象;为何是反转?因为由容器帮咱们查找及注入依赖对象,对象只是被动的承受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。

  • 用图例阐明一下?

传统程序设计下,都是被动去创立相干对象而后再组合起来:

当有了IoC/DI的容器后,在客户端类中不再被动去创立这些对象了,如图

IoC能做什么

IoC 不是一种技术,只是一种思维,一个重要的面向对象编程的法令,它能领导咱们如何设计出松耦合、更低劣的程序。

传统应用程序都是由咱们在类外部被动创立依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创立和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是 涣散耦合,这样也不便测试,利于性能复用,更重要的是使得程序的整个体系结构变得非常灵活

其实IoC对编程带来的最大扭转不是从代码上,而是从思维上,产生了“主从换位”的变动。应用程序本来是老大,要获取什么资源都是主动出击,然而在IoC/DI思维中,应用程序就变成被动的了,被动的期待IoC容器来创立并注入它所须要的资源了。

IoC很好的体现了面向对象设计法令之一—— 好莱坞法令:“别找咱们,咱们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象被动去找。

IoC和DI是什么关系

管制反转是通过依赖注入实现的,其实它们是同一个概念的不同角度形容。艰深来说就是IoC是设计思维,DI是实现形式

DI—Dependency Injection,即依赖注入:组件之间依赖关系由容器在运行期决定,形象的说,即由容器动静的将某个依赖关系注入到组件之中。依赖注入的目标并非为软件系统带来更多功能,而是为了晋升组件重用的频率,并为零碎搭建一个灵便、可扩大的平台。通过依赖注入机制,咱们只须要通过简略的配置,而无需任何代码就可指定指标须要的资源,实现本身的业务逻辑,而不须要关怀具体的资源来自何处,由谁实现。

咱们来深入分析一下:

  • 谁依赖于谁

当然是应用程序依赖于IoC容器;

  • 为什么须要依赖

应用程序须要IoC容器来提供对象须要的内部资源;

  • 谁注入谁

很显著是IoC容器注入应用程序某个对象,应用程序依赖的对象;

  • 注入了什么

就是注入某个对象所须要的内部资源(包含对象、资源、常量数据)。

  • IoC和DI由什么关系呢

其实它们是同一个概念的不同角度形容,因为管制反转概念比拟含混(可能只是了解为容器管制对象这一个层面,很难让人想到谁来保护对象关系),所以2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,绝对IoC 而言,“依赖注入”明确形容了“被注入对象依赖IoC容器配置依赖对象”。艰深来说就是IoC是设计思维,DI是实现形式

Ioc 配置的三种形式

在Spring根底 - Spring简略例子引入Spring的外围曾经给出了三种配置形式,这里再总结下;总体上目前的支流形式是 注解 + Java 配置

xml 配置

顾名思义,就是将bean的信息配置.xml文件里,通过Spring加载文件为咱们创立bean。这种形式呈现很多早前的SSM我的项目中,将第三方类库或者一些配置工具类都以这种形式进行配置,次要起因是因为第三方类不反对Spring注解。

  • 长处: 能够应用于任何场景,构造清晰,通俗易懂
  • 毛病: 配置繁琐,不易保护,枯燥无味,扩展性差

举例

  1. 配置xx.xml文件
  2. 申明命名空间和配置bean
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">    <!-- services -->    <bean id="userService" class="tech.pdai.springframework.service.UserServiceImpl">        <property name="userDao" ref="userDao"/>        <!-- additional collaborators and configuration for this bean go here -->    </bean>    <!-- more bean definitions for services go here --></beans>

Java 配置

将类的创立交给咱们配置的JavcConfig类来实现,Spring只负责保护和治理,采纳纯Java创立形式。其本质上就是把在XML上的配置申明转移到Java配置类中

  • 长处:实用于任何场景,配置不便,因为是纯Java代码,扩展性高,非常灵便
  • 毛病:因为是采纳Java类的形式,申明不显著,如果大量配置,可读性比拟差

举例

  1. 创立一个配置类, 增加@Configuration注解申明为配置类
  2. 创立办法,办法上加上@bean,该办法用于创立实例并返回,该实例创立后会交给spring治理,办法名倡议与实例名雷同(首字母小写)。注:实例类不须要加任何注解
/** * @author pdai */@Configurationpublic class BeansConfig {    /**     * @return user dao     */    @Bean("userDao")    public UserDaoImpl userDao() {        return new UserDaoImpl();    }    /**     * @return user service     */    @Bean("userService")    public UserServiceImpl userService() {        UserServiceImpl userService = new UserServiceImpl();        userService.setUserDao(userDao());        return userService;    }}

注解配置

通过在类上加注解的形式,来申明一个类交给Spring治理,Spring会主动扫描带有@Component,@Controller,@Service,@Repository这四个注解的类,而后帮咱们创立并治理,前提是须要先配置Spring的注解扫描器。

  • 长处:开发便捷,通俗易懂,不便保护。
  • 毛病:具备局限性,对于一些第三方资源,无奈增加注解。只能采纳XML或JavaConfig的形式配置

举例

  1. 对类增加@Component相干的注解,比方@Controller,@Service,@Repository
  2. 设置ComponentScan的basePackage, 比方<context:component-scan base-package='tech.pdai.springframework'>, 或者@ComponentScan("tech.pdai.springframework")注解,或者 new AnnotationConfigApplicationContext("tech.pdai.springframework")指定扫描的basePackage.
/** * @author pdai */@Servicepublic class UserServiceImpl {    /**     * user dao impl.     */    @Autowired    private UserDaoImpl userDao;    /**     * find user list.     *     * @return user list     */    public List<User> findUserList() {        return userDao.findUserList();    }}

依赖注入的三种形式

罕用的注入形式次要有三种:构造方法注入(Construct注入),setter注入,基于注解的注入(接口注入)

setter形式

  • 在XML配置形式中,property都是setter形式注入,比方上面的xml:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">    <!-- services -->    <bean id="userService" class="tech.pdai.springframework.service.UserServiceImpl">        <property name="userDao" ref="userDao"/>        <!-- additional collaborators and configuration for this bean go here -->    </bean>    <!-- more bean definitions for services go here --></beans>

实质上蕴含两步:

  1. 第一步,须要new UserServiceImpl()创建对象, 所以须要默认构造函数
  2. 第二步,调用setUserDao()函数注入userDao的值, 所以须要setUserDao()函数

所以对应的service类是这样的:

/** * @author pdai */public class UserServiceImpl {    /**     * user dao impl.     */    private UserDaoImpl userDao;    /**     * init.     */    public UserServiceImpl() {    }    /**     * find user list.     *     * @return user list     */    public List<User> findUserList() {        return this.userDao.findUserList();    }    /**     * set dao.     *     * @param userDao user dao     */    public void setUserDao(UserDaoImpl userDao) {        this.userDao = userDao;    }}
  • 在注解和Java配置形式下
/** * @author pdai */public class UserServiceImpl {    /**     * user dao impl.     */    private UserDaoImpl userDao;    /**     * find user list.     *     * @return user list     */    public List<User> findUserList() {        return this.userDao.findUserList();    }    /**     * set dao.     *     * @param userDao user dao     */    @Autowired    public void setUserDao(UserDaoImpl userDao) {        this.userDao = userDao;    }}

在Spring3.x刚推出的时候,举荐应用注入的就是这种, 然而这种形式比拟麻烦,所以在Spring4.x版本中举荐构造函数注入。

构造函数

  • 在XML配置形式中<constructor-arg>是通过结构函数参数注入,比方上面的xml:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">    <!-- services -->    <bean id="userService" class="tech.pdai.springframework.service.UserServiceImpl">        <constructor-arg name="userDao" ref="userDao"/>        <!-- additional collaborators and configuration for this bean go here -->    </bean>    <!-- more bean definitions for services go here --></beans>

实质上是new UserServiceImpl(userDao)创建对象, 所以对应的service类是这样的:

/** * @author pdai */public class UserServiceImpl {    /**     * user dao impl.     */    private final UserDaoImpl userDao;    /**     * init.     * @param userDaoImpl user dao impl     */    public UserServiceImpl(UserDaoImpl userDaoImpl) {        this.userDao = userDaoImpl;    }    /**     * find user list.     *     * @return user list     */    public List<User> findUserList() {        return this.userDao.findUserList();    }}
  • 在注解和Java配置形式下
/** * @author pdai */ @Servicepublic class UserServiceImpl {    /**     * user dao impl.     */    private final UserDaoImpl userDao;    /**     * init.     * @param userDaoImpl user dao impl     */    @Autowired // 这里@Autowired也能够省略    public UserServiceImpl(final UserDaoImpl userDaoImpl) {        this.userDao = userDaoImpl;    }    /**     * find user list.     *     * @return user list     */    public List<User> findUserList() {        return this.userDao.findUserList();    }}

在Spring4.x版本中举荐的注入形式就是这种, 具体起因看后续章节。

注解注入

以@Autowired(主动注入)注解注入为例,修饰符有三个属性:Constructor,byType,byName。默认依照byType注入。

  • constructor:通过构造方法进行主动注入,spring会匹配与构造方法参数类型统一的bean进行注入,如果有一个多参数的构造方法,一个只有一个参数的构造方法,在容器中查找到多个匹配多参数构造方法的bean,那么spring会优先将bean注入到多参数的构造方法中。
  • byName:被注入bean的id名必须与set办法后半截匹配,并且id名称的第一个单词首字母必须小写,这一点与手动set注入有点不同。
  • byType:查找所有的set办法,将合乎合乎参数类型的bean注入。

比方:

/** * @author pdai */@Servicepublic class UserServiceImpl {    /**     * user dao impl.     */    @Autowired    private UserDaoImpl userDao;    /**     * find user list.     *     * @return user list     */    public List<User> findUserList() {        return userDao.findUserList();    }}

IoC和DI应用问题小结

这里总结下理论开发中会遇到的一些问题:

为什么举荐结构器注入形式?

先来看看Spring在文档里怎么说:

The Spring team generally advocates constructor injection as it enables one to implement application components as immutable objects and to ensure that required dependencies are not null. Furthermore constructor-injected components are always returned to client (calling) code in a fully initialized state.

简略的翻译一下:这个结构器注入的形式可能保障注入的组件不可变,并且确保须要的依赖不为空。此外,结构器注入的依赖总是可能在返回客户端(组件)代码的时候保障齐全初始化的状态。

上面来简略的解释一下:

  • 依赖不可变:其实说的就是final关键字。
  • 依赖不为空(省去了咱们对其查看):当要实例化UserServiceImpl的时候,因为本人实现了有参数的构造函数,所以不会调用默认构造函数,那么就须要Spring容器传入所须要的参数,所以就两种状况:1、有该类型的参数->传入,OK 。2:无该类型的参数->报错。
  • 齐全初始化的状态:这个能够跟下面的依赖不为空联合起来,向结构器传参之前,要确保注入的内容不为空,那么必定要调用依赖组件的构造方法实现实例化。而在Java类加载实例化的过程中,构造方法是最初一步(之前如果有父类先初始化父类,而后本人的成员变量,最初才是构造方法),所以返回来的都是初始化之后的状态。

所以通常是这样的

/** * @author pdai */ @Servicepublic class UserServiceImpl {    /**     * user dao impl.     */    private final UserDaoImpl userDao;    /**     * init.     * @param userDaoImpl user dao impl     */    public UserServiceImpl(final UserDaoImpl userDaoImpl) {        this.userDao = userDaoImpl;    }}

如果应用setter注入,毛病不言而喻,对于IOC容器以外的环境,除了应用反射来提供它须要的依赖之外,无奈复用该实现类。而且将始终是个潜在的隐患,因为你不调用将始终无奈发现NPE的存在。

// 这里只是模仿一下,失常来说咱们只会裸露接口给客户端,不会裸露实现。UserServiceImpl userService = new UserServiceImpl();userService.findUserList(); // -> NullPointerException, 潜在的隐患

循环依赖的问题:应用field注入可能会导致循环依赖,即A外面注入B,B外面又注入A:

public class A {    @Autowired    private B b;}public class B {    @Autowired    private A a;}

如果应用结构器注入,在spring我的项目启动的时候,就会抛出:BeanCurrentlyInCreationException:Requested bean is currently in creation: Is there an unresolvable circular reference?从而揭示你防止循环依赖,如果是field注入的话,启动的时候不会报错,在应用那个bean的时候才会报错。

我在应用结构器注入形式时注入了太多的类导致Bad Smell怎么办?

比方当你一个Controller中注入了太多的Service类,Sonar会给你提醒相干告警

对于这个问题,阐明你的类当中有太多的责任,那么你要好好想一想是不是本人违反了类的单一性职责准则,从而导致有这么多的依赖要注入。

(pdai: 想起来一句话:所有艰难问题的解决形式,都在另外一个档次

@Autowired和@Resource以及@Inject等注解注入有何区别?

@Autowired和@Resource以及@Inject等注解注入有何区别? 这时平时在开发中,或者常见的面试题。

@Autowired

  • Autowired注解源码

在Spring 2.5 引入了 @Autowired 注解

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Autowired {  boolean required() default true;}

从Autowired注解源码上看,能够应用在上面这些中央:

@Target(ElementType.CONSTRUCTOR) #构造函数@Target(ElementType.METHOD) #办法@Target(ElementType.PARAMETER) #办法参数@Target(ElementType.FIELD) #字段、枚举的常量@Target(ElementType.ANNOTATION_TYPE) #注解

还有一个value属性,默认是true。

  • 简略总结

1、@Autowired是Spring自带的注解,通过AutowiredAnnotationBeanPostProcessor 类实现的依赖注入

2、@Autowired能够作用在CONSTRUCTOR、METHOD、PARAMETER、FIELD、ANNOTATION_TYPE

3、@Autowired默认是依据类型(byType )进行主动拆卸的

4、如果有多个类型一样的Bean候选者,须要指定依照名称(byName )进行拆卸,则须要配合@Qualifier。

指定名称后,如果Spring IOC容器中没有对应的组件bean抛出NoSuchBeanDefinitionException。也能够将@Autowired中required配置为false,如果配置为false之后,当没有找到相应bean的时候,零碎不会抛异样

  • 简略应用代码

在字段属性上。

@Autowiredprivate HelloDao helloDao;

或者

private HelloDao helloDao;public HelloDao getHelloDao() { return helloDao;}@Autowiredpublic void setHelloDao(HelloDao helloDao) { this.helloDao = helloDao;}

或者

private HelloDao helloDao;//@Autowiredpublic HelloServiceImpl(@Autowired HelloDao helloDao) { this.helloDao = helloDao;}// 结构器注入也可不写@Autowired,也能够注入胜利。

将@Autowired写在被注入的成员变量上,setter或者结构器上,就不必再xml文件中配置了。

如果有多个类型一样的Bean候选者,则默认依据设定的属性名称进行获取。如 HelloDao 在Spring中有 helloWorldDao 和 helloDao 两个Bean候选者。

@Autowiredprivate HelloDao helloDao;

首先依据类型获取,发现多个HelloDao,而后依据helloDao进行获取,如果要获取限定的其中一个候选者,联合@Qualifier进行注入。

@Autowired@Qualifier("helloWorldDao")private HelloDao helloDao;

注入名称为helloWorldDao 的Bean组件。@Qualifier("XXX") 中的 XX是 Bean 的名称,所以 @Autowired 和 @Qualifier 联合应用时,主动注入的策略就从 byType 转变成 byName 了。

多个类型一样的Bean候选者,也能够@Primary进行应用,设置首选的组件,也就是默认优先应用哪一个。

留神:应用@Qualifier 时候,如何设置的指定名称的Bean不存在,则会抛出异样,如果避免抛出异样,能够应用:

@Qualifier("xxxxyyyy")@Autowired(required = false)private HelloDao helloDao;

在SpringBoot中也能够应用@Bean+@Autowired进行组件注入,将@Autowired加到参数上,其实也能够省略。

@Beanpublic Person getPerson(@Autowired Car car){ return new Person();}// @Autowired 其实也能够省略

@Resource

  • Resource注解源码
@Target({TYPE, FIELD, METHOD})@Retention(RUNTIME)public @interface Resource {    String name() default "";    // 其余省略}

从Resource注解源码上看,能够应用在上面这些中央:

@Target(ElementType.TYPE) #接口、类、枚举、注解@Target(ElementType.FIELD) #字段、枚举的常量@Target(ElementType.METHOD) #办法

name 指定注入指定名称的组件。

  • 简略总结

1、@Resource是JSR250标准的实现,在javax.annotation包下

2、@Resource能够作用TYPE、FIELD、METHOD上

3、@Resource是默认依据属性名称进行主动拆卸的,如果有多个类型一样的Bean候选者,则能够通过name进行指定进行注入

  • 简略应用代码
@Componentpublic class SuperMan {    @Resource    private Car car;}

依照属性名称 car 注入容器中的组件。如果容器中BMW还有BYD两种类型组件。指定退出BMW。如下代码:

@Componentpublic class SuperMan {    @Resource(name = "BMW")    private Car car;}

name 的作用相似 @Qualifier

@Inject

  • Inject注解源码
@Target({ METHOD, CONSTRUCTOR, FIELD })@Retention(RUNTIME)@Documentedpublic @interface Inject {}

从Inject注解源码上看,能够应用在上面这些中央:

@Target(ElementType.CONSTRUCTOR) #构造函数@Target(ElementType.METHOD) #办法@Target(ElementType.FIELD) #字段、枚举的常量
  • 简略总结

1、@Inject是JSR330 (Dependency Injection for Java)中的标准,须要导入javax.inject.Inject jar包 ,能力实现注入

2、@Inject能够作用CONSTRUCTOR、METHOD、FIELD上

3、@Inject是依据类型进行主动拆卸的,如果须要按名称进行拆卸,则须要配合@Named;

  • 简略应用代码
@Injectprivate Car car;

指定退出BMW组件。

@Inject@Named("BMW")private Car car;

@Named 的作用相似 @Qualifier!

总结

1、@Autowired是Spring自带的,@Resource是JSR250标准实现的,@Inject是JSR330标准实现的

2、@Autowired、@Inject用法根本一样,不同的是@Inject没有required属性

3、@Autowired、@Inject是默认依照类型匹配的,@Resource是依照名称匹配的

4、@Autowired如果须要依照名称匹配须要和@Qualifier一起应用,@Inject和@Named一起应用,@Resource则通过name进行指定

如果你还冀望源码层了解,我给你找了一篇文章Spring源码剖析@Autowired、@Resource注解的区别

参考文章

Inversion of Control Containers and the Dependency Injection pattern

https://www.iteye.com/blog/ji...

https://blog.csdn.net/qq_3563...

https://www.cnblogs.com/diand...

更多文章

首先, 从Spring框架的整体架构和组成对整体框架有个认知。
  • Spring根底 - Spring和Spring框架组成

    • Spring是什么?它是怎么诞生的?有哪些次要的组件和外围性能呢? 本文通过这几个问题帮忙你构筑Spring和Spring Framework的整体认知。
其次,通过案例引出Spring的外围(IoC和AOP),同时对IoC和AOP进行案例应用剖析。
  • Spring根底 - Spring简略例子引入Spring的外围

    • 上文中咱们简略介绍了Spring和Spring Framework的组件,那么这些Spring Framework组件是如何配合工作的呢?本文次要承接上文,向你展现Spring Framework组件的典型利用场景和基于这个场景设计出的简略案例,并以此引出Spring的外围要点,比方IOC和AOP等;在此基础上还引入了不同的配置形式, 如XML,Java配置和注解形式的差别。
  • Spring根底 - Spring外围之管制反转(IOC)

    • 在Spring根底 - Spring简略例子引入Spring的外围中向你展现了IoC的根底含意,同时以此发散了一些IoC相干知识点; 本节将在此基础上进一步解读IOC的含意以及IOC的应用形式
  • Spring根底 - Spring外围之面向切面编程(AOP)

    • 在Spring根底 - Spring简略例子引入Spring的外围中向你展现了AOP的根底含意,同时以此发散了一些AOP相干知识点; 本节将在此基础上进一步解读AOP的含意以及AOP的应用形式。
基于Spring框架和IOC,AOP的根底,为构建下层web利用,须要进一步学习SpringMVC。
  • Spring根底 - SpringMVC申请流程和案例

    • 前文咱们介绍了Spring框架和Spring框架中最为重要的两个技术点(IOC和AOP),那咱们如何更好的构建下层的利用呢(比方web 利用),这便是SpringMVC;Spring MVC是Spring在Spring Container Core和AOP等技术根底上,遵循上述Web MVC的标准推出的web开发框架,目标是为了简化Java栈的web开发。 本文次要介绍SpringMVC的申请流程和根底案例的编写和运行。
Spring进阶 - IoC,AOP以及SpringMVC的源码剖析
  • Spring进阶 - Spring IOC实现原理详解之IOC体系结构设计

    • 在对IoC有了初步的认知后,咱们开始对IOC的实现原理进行深刻了解。本文将帮忙你站在设计者的角度去看IOC最顶层的结构设计
  • Spring进阶 - Spring IOC实现原理详解之IOC初始化流程

    • 上文,咱们看了IOC设计要点和设计构造;紧接着这篇,咱们能够看下源码的实现了:Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的
  • Spring进阶 - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)

    • 上文,咱们看了IOC设计要点和设计构造;以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的;容器中寄存的是Bean的定义即BeanDefinition放到beanDefinitionMap中,实质上是一个ConcurrentHashMap<String, Object>;并且BeanDefinition接口中蕴含了这个类的Class信息以及是否是单例等。那么如何从BeanDefinition中实例化Bean对象呢,这是本文次要钻研的内容?
  • Spring进阶 - Spring AOP实现原理详解之切面实现

    • 前文,咱们剖析了Spring IOC的初始化过程和Bean的生命周期等,而Spring AOP也是基于IOC的Bean加载来实现的。本文次要介绍Spring AOP原理解析的切面实现过程(将切面类的所有切面办法依据应用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor,为后续交给代理加强实现做筹备的过程)。
  • Spring进阶 - Spring AOP实现原理详解之AOP代理

    • 上文咱们介绍了Spring AOP原理解析的切面实现过程(将切面类的所有切面办法依据应用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor)。本文在此基础上持续介绍,代理(cglib代理和JDK代理)的实现过程。
  • Spring进阶 - Spring AOP实现原理详解之Cglib代理实现

    • 咱们在前文中曾经介绍了SpringAOP的切面实现和创立动静代理的过程,那么动静代理是如何工作的呢?本文次要介绍Cglib动静代理的案例和SpringAOP实现的原理。
  • Spring进阶 - Spring AOP实现原理详解之JDK代理实现

    • 上文咱们学习了SpringAOP Cglib动静代理的实现,本文次要是SpringAOP JDK动静代理的案例和实现局部。
  • Spring进阶 - SpringMVC实现原理之DispatcherServlet初始化的过程

    • 前文咱们有了IOC的源码根底以及SpringMVC的根底,咱们便能够进一步深刻了解SpringMVC次要实现原理,蕴含DispatcherServlet的初始化过程和DispatcherServlet解决申请的过程的源码解析。本文是第一篇:DispatcherServlet的初始化过程的源码解析。
  • Spring进阶 - SpringMVC实现原理之DispatcherServlet解决申请的过程

    • 前文咱们有了IOC的源码根底以及SpringMVC的根底,咱们便能够进一步深刻了解SpringMVC次要实现原理,蕴含DispatcherServlet的初始化过程和DispatcherServlet解决申请的过程的源码解析。本文是第二篇:DispatcherServlet解决申请的过程的源码解析。