开始之前:本文满满的图片。请大家在阅读之前准备好流量,以防爆表。哈哈。第一次写IOC的文章,希望大家多多支持,谢谢。
本文主要针对ClasspathXmlApplicationContext(还有与之类似的FileSystemXml...)的整体初始化流程做讲解。如有疑问可以加QQ群: 77174608 来讨论。
主题开始:
读源码准备的环境:
maven, logback基础知识, Spring 相关使用经验。
进入正文: 首先开始pom.xml
<properties> <spring.version>4.3.14.RELEASE</spring.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-asm --> <!-- 注意,这里是第一个坑,在高版本的spring中是不需要手动引入该依赖了,如果引入则会抛出 java.lang.IncompatibleClassChangeError: class org.springframework.core.type.classreading.ClassMetadataReadingVisitor has interface org.springframework.asm.ClassVisitor as super class 异常 --> <!--<dependency>--> <!--<groupId>org.springframework</groupId>--> <!--<artifactId>spring-asm</artifactId>--> <!--<version>3.1.4.RELEASE</version>--> <!--</dependency>--> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.7.21</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.7</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>${spring.version}</version> </dependency> </dependencies>
logback配置:
<appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n </pattern> </encoder> </appender> <logger name="org.springframework" additivity="false" level="debug"> <appender-ref ref="console"/> </logger>
我这里使用了自动扫包,所以beans.xml配置为:
<context:annotation-config/> <context:component-scan base-package="com.autorun.spring.demo"/>
ok, 环境已经基本已经搞定,我们开始写基本类
package com.autorun.spring.demo.beans; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * @author Autorun * Created by Autorun on 2018/3/4. */ @Component public class A { @Autowired private B b; @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } A a = (A) o; return b != null ? b.equals(a.b) : a.b == null; } @Override public int hashCode() { return b != null ? b.hashCode() : 0; } @Override public String toString() { return "A{" + ", b=" + b + '}'; } }
package com.autorun.spring.demo.beans; import org.springframework.stereotype.Component; /** * @author Autorun * Created by Autorun on 2018/3/4. */ @Component public class B { }
然后创建主类(当然, 目前spring还是主要用于web开发,有用过springboot的童鞋应该对这种玩法有所了解。不再赘述):
public class Application { public static void main(String[] args) { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans-parent.xml"); ctx.setDisplayName("parent"); /// ctx.start(); A a = ctx.getBean(A.class); System.out.println(a); B b = ctx.getBean(B.class); System.out.println(b); }
以上就是环境准备篇。毕竟基础。下一篇将正式开始源码拆解。 前几篇文章会粗略的走一遍加载,目的是让大家熟悉一下整体流程。之后会对每个组件进行讲解。谢谢大家支持