• BeanFactory接口
  • Resource接口
  • ResourceLoader接口
  • Aware接口
  • BeanDefinition接口
  • InitializingBean接口
  • DisposableBean接口
  • ImportBeanDefinitionRegistrar接口
  • ImportSelector接口
  • AliasRegistry接口
  • FactoryBean接口
  • BeanFactoryPostProcessor接口
  • BeanPostProcessor接口

1. BeanFactory接口

(1)概念

  • BeanFactory是Spring容器的顶层接口定义了IOC容器的基本规范:定义了获取bean,判断bean等API
  • 有三个子接口(二级接口)
  • ListableBeanFactory
  • HierarchicalBeanFactory
  • AutowireCapableBeanFactory
  • 子类中最重要的实现类:DefaultListableBeanFactory

(2)其他

  • 我们经常使用的一些BeanFactory的实现类
  • DefaultListableBeanFactory:非常重要,几乎所有BeanFactory都会内置该实现类来完成各种功能
  • AnnotationConfigApplicationContext:注解形式配置
  • ClassPathXmlApplicationContext:在classPath中的xml配置文件
  • FileSystemXmlApplicationContext:自定义配置文件路径
  • WebApplicationContext:主要用于web应用,内置了web上下文环境

(3)源码

  • BeanFactory接口
// 定义获取bean及bean的各种属性
public interface BeanFactory {

    //1. 用来引用一个实例,或把它和工厂产生的Bean区分开,就是说,如果一个FactoryBean的名字为a,那么,&a会得到那个Factory
	String FACTORY_BEAN_PREFIX = "&";

    //2. 五种不同形式的getBean方法,获取实例
	Object getBean(String name) throws BeansException;
	<T> T getBean(String name, Class<T> requiredType) throws BeansException;
	Object getBean(String name, Object... args) throws BeansException;
	<T> T getBean(Class<T> requiredType) throws BeansException;
	<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

    //3. 获取BeanProvider
	<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
	<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);

    //4. 容器是否包含beanName
	boolean containsBean(String name);

    //5. bean是否单例 / 多例
	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

    //6. bean的名称/类型 是否匹配
	boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
	boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
    
    //7. 根据beanName获取bean类型
	@Nullable
	Class<?> getType(String name) throws NoSuchBeanDefinitionException;
	@Nullable
	Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException;

    //8. 获取bean的别名
	String[] getAliases(String name);

}

2. Resource接口

(1)概念

  • 为什么要定义Resouce接口
  • 在日常程序开发中,处理外部资源是很繁琐的事情,我们可能需要处理URL资源、File资源资源、ClassPath相关资源、服务器相关资源等等很多资源
  • 处理这些资源需要使用不同的接口,这就增加了我们系统的复杂性;而且处理这些资源步骤都是类似的(打开资源、读取资源、关闭资源)
  • 因此如果能抽象出一个统一的接口来对这些底层资源进行统一访问会很方便,而且使我们系统更加简洁,都是对不同的底层资源使用同一个接口进行访问
  • Spring的Resource接口代表底层外部资源,提供了对底层外部资源的一致性访问接口,里面封装了大量模板方法

(2)常用的Spring内置实现类

  • Spring中提供了很多Resource接口的实现类,主要有
  • ByteArrayResource
  • ClassPathResource(常用):通过 ClassPathResource 以类路径的方式进行访问
  • 使用默认ClassLoader加载:public ClassPathResource(String path)
  • 使用指定ClassLoader加载:public ClassPathResource(String path, ClassLoader classLoader)
  • 使用指定的类加载“path”类路径资源:public ClassPathResource(String path, Class<?> clazz)
  • DescriptiveResource
  • FileSystemResource(常用):通过 FileSystemResource 以文件系统绝对路径的方式进行访问
File file = new File("d:/test.txt");
Resource resource = new FileSystemResource(file);
  • InputStreamResource
  • PortletContextResource
  • ServletContextResource(常用):通过 ServletContextResource 以相对于Web应用根目录的方式进行访问
  • UrlResource(常用):通过java.net.URL来访问资源,当然它也支持File格式
  • "http://地址"
  • "ftp://地址"
  • "file:d:/test.txt"

(3)源码

  • Resource接口
public interface Resource extends InputStreamSource {

    //当前Resource代表的底层资源是否存在
	boolean exists();
    //当前Resource代表的底层资源是否可读
	default boolean isReadable() {
		return exists();
	}
    //当前Resource代表的底层资源是否已经打开,如果返回true,则只能被读取一次然后关闭以避免资源泄露;常见的Resource实现一般返回false
	default boolean isOpen() {
		return false;
	}
    当前Resource代表的底层资源是否是文件
	default boolean isFile() {
		return false;
	}
    //如果当前Resource代表的底层资源能由java.util.URL代表,则返回该URL,否则抛出IOException
	URL getURL() throws IOException;
    //如果当前Resource代表的底层资源能由java.util.URI代表,则返回该URI,否则抛出IOException
	URI getURI() throws IOException;
    //如果当前Resource代表的底层资源能由java.io.File代表,则返回该File,否则抛出IOException
	File getFile() throws IOException;
    //
	default ReadableByteChannel readableChannel() throws IOException {
		return Channels.newChannel(getInputStream());
	}
    //当前Resource代表的底层文件资源的长度,一般是值代表的文件资源的长度
	long contentLength() throws IOException;
    //当前Resource代表的底层资源的最后修改时间
	long lastModified() throws IOException;
    //用于创建相对于当前Resource代表的底层资源的资源
    //比如当前Resource代表文件资源“d:/test/”则createRelative(“test.txt”)将返回表文件资源“d:/test/test.txt”Resource资源
	Resource createRelative(String relativePath) throws IOException;
    //当前Resource代表的底层文件资源的文件路径
    //比如File资源“file://d:/test.txt”将返回“d:/test.txt”
    //而URL资源http://www.javass.cn将返回“”,因为只返回文件路径
	@Nullable
	String getFilename();
    //当前Resource代表的底层资源的描述符,通常就是资源的全路径(实际文件名或实际URL地址)
	String getDescription();
}
  • Resource接口的父接口InputStreamSource
public interface InputStreamSource {
    //用来获取java.io.InputStream对象,这个输入流指向资源本身
	InputStream getInputStream() throws IOException;
}

3. ResourceLoader接口

(1)概念

  • ResourceLoader接口用来加载Resource资源
  • 所有的ApplicationContext类都实现了ResourceLoader接口,所以我们可以使用context来加载resource
  • 不同类型的ApplicationContext会返回不同的Resource

(2)使用

  • 当你在特定的应用程序上下文上调用getResource(),并且指定的位置路径没有特定的前缀时,你将返回适合该特定应用程序上下文的资源类型
  • 假设对ClassPathXmlApplicationContext实例执行了以下代码片段:他会返回和ApplicationContext相对应的Resource实现
  • ClassPathXmlApplicationContext返回ClassPathResource
  • FileSystemXmlApplicationContext返回FileSystemResource
  • WebApplicationContext返回ServletContextResource
Resource template = ctx.getResource("some/resource/path/myTemplate.txt");
  • 当然,你可以强制ClassPathResource使用,而不管ApplicationContext到底是什么,使用的方法就是在资源路径前面加前缀
Resource template1 = ctx.getResource("classpath:some/resource/path/myTemplate.txt");
Resource template2 = ctx.getResource("http://myhost.com/resource/path/myTemplate.txt");
Resource template3 = ctx.getResource("file:///some/resource/path/myTemplate.txt");
Resource[] template4 = ctx.getResources("file:///some/resource/path/my**a.txt");

(3)源码

public interface ResourceLoader {
	/** Pseudo URL prefix for loading from the class path: "classpath:". */
	String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX;
    //根据路径返回对应的Resource的实现类对象
	Resource getResource(String location);
    //返回当前可用的classLoader对象
	@Nullable
	ClassLoader getClassLoader();
}

(4)Reference




4. Aware接口

(1)概念

  • Aware中文翻译:感知,意识到,获取到
  • 在Spring中有很多Aware接口,实现了这些接口后,我们可以在自己写的bean中感知(获取)到对应的Spring组件
  • 比如实现了ApplicationContextAware接口的类,能够获取到ApplicationContext
  • 比如实现了BeanFactoryAware接口的类,能够获取到BeanFactory对象
  • 注:Spring会在实例化bean之后,执行所有的Aware接口中的方法,进行对应的内容填充

(2)Spring提供的Aware接口

  • ApplicationContextAware:获取ApplicationContext对象
  • ApplicationEventPublisherAware
  • BeanClassLoaderAware
  • BeanFactoryAware:获取BeanFactory对象
  • BeanNameAware:获取beanName对象
  • BootstrapContextAware
  • LoadTimeWeaverAware
  • MessageSourceAware
  • NotificationPublisherAware
  • ResourceLoaderAware
  • ServletConfigAware
  • ServletContextAware

(3)例子(以BeanFactoryAware为例)

(4)源码

  • Aware源码,什么都没有hhh
public interface Aware {
}
  • Spring提供的Aware子类接口(以BeanFactoryAware为例)
public interface BeanFactoryAware extends Aware {

	void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}

5. BeanDefinition接口

(1)概念

  • BeanDefinition中存放了Spring bean的描述信息(注册信息)
  • 如该bean是否单例,全限类名等等
  • BeanDefinition在springBean加载过程中的作用(简单描述)
  • 1. spring会加载所有符合要求的class(从xml或者注解中)
  • 2. 解析这些类的相关信息
  • 3. 把解析完的信息存放在BeanDefinition中
  • 4. 根据bean的scope属性进行实例化
  • 5. 执行该bean实现的一些接口,比如Aware等

(2)源码

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

    //单例字符串singleton
	String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
    //原型字符串prototype
	String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
    //表示该BeanDefinition的角色是应用角色,说白了就是程序员注入到IOC容器中的bean
	int ROLE_APPLICATION = 0;
    //某些复杂的配置类
	int ROLE_SUPPORT = 1;
    //spring内部使用的bean角色,反正不是程序员手动注入的bean
	int ROLE_INFRASTRUCTURE = 2;

	// set和get方法

    //0. 设置父bean的名称
	void setParentName(@Nullable String parentName);

	@Nullable
	String getParentName();

    //1. 设置当前bean definition的class类名
    //   可以使用BeanFactoryPostProcessor这个接口去修改class类名
	void setBeanClassName(@Nullable String beanClassName);

	@Nullable
	String getBeanClassName();

    //2. 设置作用域,是单例还是原型
	void setScope(@Nullable String scope);

	@Nullable
	String getScope();

    //3. 设置是否是懒加载
	void setLazyInit(boolean lazyInit);

	boolean isLazyInit();

    //4. 设置需要先加载的依赖的类名字数组,bean工厂会优化初始化那些bean
	void setDependsOn(@Nullable String... dependsOn);

	@Nullable
	String[] getDependsOn();

    //5. 设置是否适合给其他类做自动装配
	void setAutowireCandidate(boolean autowireCandidate);

	boolean isAutowireCandidate();

    //6. 设置是否优先自动装配
	void setPrimary(boolean primary);

	boolean isPrimary();

    //7. 设置FactoryBean的名字
	void setFactoryBeanName(@Nullable String factoryBeanName);

	@Nullable
	String getFactoryBeanName();

    //8. FactoryMethod的名字配置(工厂方式生成Bean的时候用)
	void setFactoryMethodName(@Nullable String factoryMethodName);

	@Nullable
	String getFactoryMethodName();

    //9. 获取构造函数的参数
	ConstructorArgumentValues getConstructorArgumentValues();

	default boolean hasConstructorArgumentValues() {
		return !getConstructorArgumentValues().isEmpty();
	}

    //10. 返回当前bean的属性值,而且这些值也可以在BeanFactoryPostProcessor中进行修改
	MutablePropertyValues getPropertyValues();

	default boolean hasPropertyValues() {
		return !getPropertyValues().isEmpty();
	}

    //11. 设置初始化方法,对应@PostConstruct
	void setInitMethodName(@Nullable String initMethodName);

	@Nullable
	String getInitMethodName();

    //12. 设置销毁方法的名称,对应@PreDestory
	void setDestroyMethodName(@Nullable String destroyMethodName);

	@Nullable
	String getDestroyMethodName();

    //13. 
	void setRole(int role);

	int getRole();

    //14. 描述
	void setDescription(@Nullable String description);

	@Nullable
	String getDescription();

	// 只读方法

	//1. 是否单例
	ResolvableType getResolvableType();
    //2. 是否单例
	boolean isSingleton();
    //3. 是否多例
	boolean isPrototype();
    //4. 是否抽象
	boolean isAbstract();
    //5. 资源描述
	@Nullable
	String getResourceDescription();
    //6. 获取原始的BeanDefinition对象
	@Nullable
	BeanDefinition getOriginatingBeanDefinition();

}

6. InitializingBean接口

(1)概念

  • 该接口为bean提供了初始化方法的方式,需要重写afterPropertiesSet方法:凡是继承该接口的类,在初始化bean时都会执行该方法
  • InitializingBean和init-method和@PostConstruct功能类似,但执行顺序还有原理存在区别

(2)例子


  • 总结:执行顺序
  • 1. constructor:实例化bean
  • 2. @Autowired:bean的依赖注入
  • 3. @PostConstruct 执行
  • 4. InitializingBean 的 afterPropertiesSet 执行
  • 5. init-method 执行

(3)源码

public interface InitializingBean {
    //在BeanFactory设置了提供的所有bean属性后调用
	void afterPropertiesSet() throws Exception;
}

7. DisposableBean接口

(1)概念

  • 与InitializingBean接口的方法类似
  • 执行顺序
  • 1. @PreDestroy 执行
  • 2. DisposableBean的 destory()方法
  • 3. destroy-method 执行

(3)源码

public interface DisposableBean {

	void destroy() throws Exception;
}

8. ImportBeanDefinitionRegistrar接口

(1)概念

  • ImportBeanDefinitionRegistrar接口提供了一个动态注入bean的方法,我们可以通过实现这个接口,自己手动注入bean。Spring内部bean的注入大部分都是这个套路
  • 使用这个接口需要配合@import注解:快速将一个Bean注册到IOC容器中

9. ImportSelector接口


10. AliasRegistry接口

(1)概念

  • 主要是对spring Bean的别名进行管理的顶级接口,主要对别名进行增删功能
  • 它有几个比较重要的子接口或者实现类
  • BeanDefinitionRegistry接口:继承AliasRegistry接口,扩展了对BeanDefinition注册操作的功能
  • 默认实现类:SimpleAliasRegistry,可以使用这个类来进行别名管理

(2)源码

  • AliasRegistry
//用于管理别名的公共接口,定义对别名的简单增删操作
public interface AliasRegistry {

	//注册表中给name注册一个别名
	void registerAlias(String name, String alias);

	//移除注册表中的别名alias
	void removeAlias(String alias);

	//校验注册表中是否存在别名name
	boolean isAlias(String name);

	//在注册表中获取给定的所有别名信息
	String[] getAliases(String name);
}
  • BeanDefinitionRegistry
//定义对BeanDefinition的各种增删改操作
public interface BeanDefinitionRegistry extends AliasRegistry {

    //注册BeanDefinition到注册表
	void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException;

    //移除注册表中beanName的BeanDefinition
	void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    //获取注册表中beanName的BeanDefinition
	BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    //检查此注册表是否包含具有给定名称的BeanDefinition
	boolean containsBeanDefinition(String beanName);

    //返回此注册表中定义的所有bean的名称
	String[] getBeanDefinitionNames();

    //返回注册表中定义的bean的数目
	int getBeanDefinitionCount();

    //确定给定bean名称是否已在该注册表中使用
	boolean isBeanNameInUse(String beanName);

}

11. FactoryBean接口

(1)概念

  • FactoryBean是个工厂Bean,可以生成某一个类型Bean的实例对象
  • 在Spring容器中有两类的Bean,一类是普通的Bean,一类是工厂Bean
  • 这两种Bean都是被Spring的容器进行管理的。而Spring也提供了一个接口用于扩展工厂Bean,我们只要实现FactoryBean接口即可

(2)使用例子

 

(3)源码

public interface FactoryBean<T> {

	String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";

    //返回当前bean工厂创建的bean的实例
	@Nullable
	T getObject() throws Exception;

    //返回当前bean工厂创建的bean的类型
	@Nullable
	Class<?> getObjectType();

    //判断当前类是否是单例模式
	default boolean isSingleton() {
		return true;
	}

}

12. BeanFactoryPostProcessor

(1)概念

  • BeanFactoryPostProcessor是bean工厂的beanDefinition处理容器:说通俗一点就是可以管理我们的bean工厂内所有beanDefinition(未实例化)数据,可以随心所欲的修改属性

(3)源码

@FunctionalInterface
public interface BeanFactoryPostProcessor {

    //钩子方法
    //入参为当前的工厂对象,我们可以通过这个beanFactory获取beanDefinition的信息
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

13. BeanPostProcessor

(1)概念

  • bean的后置处理器接口,在依赖注入的初始化方法前后进行调用
  • 对所有bean进行前置和后置处理

(2)执行顺序

java spring api接口废弃注解 spring的接口_java

(3)源码

public interface BeanPostProcessor {

    //bean初始化方法调用前被调用
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
    //bean初始化方法调用后被调用
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
}