spring整体架构
基础接口
Resource+ResourceLoader
Resource代表spring中的资源的高度抽象,spring中所有的加载最终都是由Resource来实现的,具体根据不同的需要实现不同的接口,可以来自于二进制文件,可以来自于网络、磁盘等等情况
通过Resource接口获取资源
Resource接口的实现类有:
Resource接口继承了InputStreamSource
接口,InputStreamSource
接口中有一个方法:getInputStream()
,所以汇总起来,Resource接口中共有以下方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| public class ResourceTest {
@Test public void TestClassPath() throws IOException{ Resource resource = new ClassPathResource("test.txt");
if (resource.exists()) { System.out.println("文件存在"); }
if (resource.isReadable()) { System.out.println("文件可读"); }
if (resource.isOpen()) { System.out.println("资源文件已打开"); }
System.out.println(resource.getURL()); System.out.println(resource.getURI()); resource.getFile(); System.out.println(resource.contentLength()); System.out.println(resource.lastModified()); resource.createRelative("MyFile"); System.out.println(resource.getFilename()); System.out.println(resource.getDescription());
if (resource.isReadable()) { InputStream is = resource.getInputStream(); System.out.println(is); is.close(); }
}
@Test public void TestFileSystem() throws IOException { Resource resource = new FileSystemResource("D:\\test.txt"); System.out.println(resource.getFilename()); }
@Test public void TestUrl() throws MalformedURLException{ Resource resource = new UrlResource("http://docs.spring.io/spring/docs/4.0.0.M1/spring-framework-reference/pdf/spring-framework-reference.pdf"); System.out.println(resource.getFilename()); }
@Test public void testByteArray() throws IOException { ByteArrayResource resource = new ByteArrayResource("Hello".getBytes()); System.out.println(resource.getInputStream());
}
@Test public void testInputStream() throws Exception { InputStream is = new FileInputStream("D\\test.txt"); InputStreamResource resource = new InputStreamResource(is); InputStream is2 = resource.getInputStream(); System.out.println(is2); is.close(); } }
|
通过ResourceLoader接口获取资源
Spring框架为了更方便的获取资源,尽量弱化程序员对各个Resource接口的实现类的感知,定义了另一个ResourceLoader
接口。该接口的getResource(String location)
方法可以用来获取资源。它的DefaultResourceLoader实现类可以适用于所有的环境,可以返回ClassPathResource、UrlResource等。
ResourceLoader在进行加载资源时需要使用前缀来指定需要加载:“classpath:path”表示返回ClasspathResource,“http://path”和“file:path”表示返回UrlResource资源,如果不加前缀则需要根据当前上下文来决定,DefaultResourceLoader默认实现是加载classpath资源。
1 2 3 4 5 6 7 8 9 10 11 12
| @Test public void testResourceLoader() {
ResourceLoader loader = new DefaultResourceLoader(); Resource resource = loader.getResource("http://www.baidu.com"); System.out.println(resource instanceof UrlResource); resource = loader.getResource("classpath:test.txt"); System.out.println(resource instanceof ClassPathResource); resource = loader.getResource("test.txt"); System.out.println(resource instanceof ClassPathResource);
}
|
ResourceLoader是一个策略模式,什么是策略模式:策略(Strategy)模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。属于对象行为模式。
抽象策略:ResourceLoader
具体策略:ResourceLoader的DefaultResource的具体实现
环境类:AbstractApplicationContext、因为AbstractApplicationContext初始化的时候必须进行resourcePatternResolver赋值
BeanFactory
BeanFactory
HierarchicalBeanFactory:定义父子工厂(父子容器)getParentBeanFactory和containsLocalBean
ListableBeanFacotory:的实现是DefaultListableBeanFactory,保存了ioc容器中的核心信息(只保存定义信息不保存具体的对象):serializableFactories、beanDefinitionMap、singletonBeanNamesByType、beanDefinitionNames等
AutowireCapableBeanFactory:提供自动装配能力,提供了createbean、autowireBean、configureBean、initializeBean、destroyBean等一系列自动装配的自定义方法
AnnotationApplicationContext组合了档案馆,他有自动装配能力。
BeanDefinition
BeanDefinition也就是bean的定义信息,所有加载过来的Resource全部都要先转化为BeanDefinition,在BeanDefinition中有一个map对象,用于保存所有bean的信息比如bean的作用域,bean的注入模型,bean是否是懒加载等等信息
BeanDefinitionReader
Resource加载的途径有好多种,可能是xml文件、可能是注解,可能是本地的二进制文件、可能是网络的二进制文件等等,这个信息全部要通过BeanDefinitionReader进行读取,通过Document对象转化为Dom元素。所以BeanDefinitionReader就是Bean定义信息的加载器
BeanDefinitionRegistry
所有的bean信息都要转化为BeanDefinition,但是我们知道我们所有的bean对象都是存放在BeanFactory中,那么这个存放的这个过程是怎样的?所以BeanDefinitionRegistry的所用就是把我们的beandefinition存放到BeanFactory中,其中定义了关于 BeanDefinition 的注册、移除、查询等一系列的操作。
实现BeanDefinitionRegistry接口的有三个类:DefaultListableBeanFactory、GenericApplicationContext、SimpleBeanDefinitionRegistry,其中 GenericApplicationContext 底层调用的是 DefaultListableBeanFactory 中的实现方法,所以严格意义上来说,只有两个实现类。
ApplicationContext
1、ioc事件派发器
2、国际化解析
3、bean工厂功能—自动装配被组合进来的
4、资源解析功能
通过ApplicationContext获取资源
所有ApplicationContext实例都实现了ResourceLoader接口,因此我们在使用Spring容器时,可以不去过于计较底层Resource的实现,也不需要自己创建Resource实现类,而是直接使用applicationContext.getResource(),获取到bean容器本身的Resource,进而取到相关的资源信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class MyResource implements ApplicationContextAware { private ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; }
public void resource() throws IOException { Resource resource = applicationContext.getResource("file:D:\\test.txt"); System.out.println(resource.getFilename()); System.out.println(resource.contentLength());
}
}
|
配置xml文件:
1
| <bean id="myResource" class="com.spring.test.MyResource"></bean>
|
测试类:
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class App { public static void main(String[] args) { @SuppressWarnings("resource") ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-resource.xml"); MyResource myResource = (MyResource) context.getBean("myResource"); try { myResource.resource(); } catch (IOException e) { e.printStackTrace(); }
} }
|
Aware
生命周期-后置处理器
BeanFactoryPostProcessor
InitializingBean
BeanPostProcessor
在一个Bean初始化前后进行功能增强。
BeanPostProcessor:后置增强普通的Bean组件
BeanFactoryPostProcessor:后置增强BeanFactory