Spring狭义上特指Spring FrameWork,Spring有两个核心模块:IOC和AOP。
IoC
控制反转(Inversion of Control)是一种软件设计原则,它将控制权从应用程序代码中转移到外部容器或框架中。在Java中,Spring框架是一个常用的实现控制反转的工具。通过依赖注入(Dependency Injection)和面向接口编程等技术,Spring框架可以实现IoC,使得应用程序更加灵活、可扩展和易于维护。
在IoC容器中,对象的创建、组装和管理都由容器来负责,而不是由程序员手动管理。这样一来,程序员只需要关注业务逻辑的编写,而不用操心对象的创建和管理,降低了耦合度,提高了代码的可测试性和可维护性。
IoC的核心思想是通过依赖注入实现对象之间的解耦,使得代码更加灵活、可扩展和易于理解。
总结:Spring通过IoC容器来管理所有Java对象的实例化和初始化,控制对象与对象之间的依赖关系。将由IoC容器管理的Java对象称为Spring Bean,它与使用关键词new创建的Java对象没有任何区别。
Spring通过注解自动装配步骤
1、引入依赖
2、开启组件扫描
3、使用注解定义Bean
@Component:表示我是Bean,可以作用在应用的任何层次,例如Service层,Dao层等。
@Repository:用于数据访问层(Dao层)的类标识为Bean,功能与@Component相同。
@Service:用于业务层(Service层)。
@Controller:用于控制层(Controller层),用于将控制层的类标识为Bean。
4、依赖注入
最简单的bean容器
定义一个简单的bean容器BeanFactory,内部包含一个map用以保存bean,只有注册bean和获取bean两个方法。
package com.cjd;
import java.util.HashMap;
import java.util.Map;
public class BeanFactory {
private Map<String,Object> beanMap = new HashMap<>();
public void registerBean(String name,Object bean){
beanMap.put(name, bean);
}
public Object getBean(String name){
return beanMap.get(name);
}
}
测试:
import com.cjd.BeanFactory;
import org.junit.jupiter.api.Test;
public class SimpleBeanContainerTest {
@Test
public void testGetBean() {
BeanFactory beanFactory = new BeanFactory();
beanFactory.registerBean("helloService",new HelloService());
HelloService helloService = (HelloService) beanFactory.getBean("helloService");
System.out.println(helloService.sayHello());
}
}
public class HelloService {
public String sayHello(){
System.out.println("hello");
return "hello";
}
}
BeanDefiniton和BeanDefinitionRegistry
BeanDefinition:定义Bean的信息,包含bean的class类型,构造参数、属性等信息,每个bean对应一个BeanDefinition的实例。(简化的BeanDefinition只包含bean的class类型)
BeanDefinitionRegistry:BeanDefinition注册表接口,定义注册BeanDefinition的方法。
SingletonBeanRegistry和它的实现类DefaultSingletonBeanRegistry:定义添加和获取单例bean的方法。
bean容器作为BeanDefinitionRegistry和SingletonBeanRegistry的实现类,具备两者的能力。向bean容器注册BeanDefinition后,使用bean时才会实例化。
(
在 Spring 框架中,通常不直接使用 BeanDefinition
的构造函数来创建 BeanDefinition 对象。相反,通常会使用 BeanDefinitionRegistry
接口的方法来注册和管理 BeanDefinition。
例如,你可以使用 DefaultListableBeanFactory
或 GenericApplicationContext
(它们都实现了 BeanDefinitionRegistry
接口)来注册 BeanDefinition。
在这个示例中,我们首先创建了一个 DefaultListableBeanFactory
对象,然后使用 BeanDefinitionBuilder
创建了一个 BeanDefinition,并将其注册到了 beanFactory 中。
如果需要动态地注册和管理 BeanDefinition,建议使用Spring提供的工具类和接口,而不是直接调用构造函数来创建 BeanDefinition 对象。这样可以更好地与Spring框架整合,确保正确地管理和注入依赖,同时也更符合Spring框架的设计理念。
)
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
public class BeanDefinitionAndBeanDefinitionRegistryTest {
@Test
public void testBeanFactory() throws Exception{
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(HelloService.class);
GenericBeanDefinition definition = (GenericBeanDefinition) builder.getRawBeanDefinition();
beanFactory.registerBeanDefinition("helloService",definition);
}
}
资源和资源加载器
resource是资源的抽象和访问接口,简单实现了三个实现类。
FileSystemResource:文件系统资源的实现类
ClassPathResource:classpath下资源的实现类
UrlResource:对java.net.URL进行资源定位的实现类
ResourceLoader接口则是资源查找定位策略的抽象,DefaultResourceLoader是其默认实现类
BeanFactoryPostProcessor和BeanPostProcessor:
这两个是spring框架中具有重量级地位的两个接口,理解了这两个接口的作用,基本就理解spring的核心原理了。
BeanFactoryPostProcessor:
它是spring提供的容器扩展机制,允许我们在bean实例化之前修改bean的定义信息即BeanDefinition的信息。其重要的实现类有PropertyPlaceholderConfigurer和CustomEditorConfigurer。
PropertyPlaceholderConfigurer:用properties文件的配置值替换xml文件中的占位符
CustomEditorConfigurer:实现类型转换
BeanPostProcessor:
它也是spring提供的容器扩展机制,不同于BeanFactoryPostProcessor的是,BeanPostProcessor在bean实例化后修改bean或替换bean。BeanPostProcessor是后面实现AOP的关键。
BeanPostProcessor的两个方法分别在bean执行初始化方法之前和之后执行。
public interface BeanPostProcessor {
/**
* 在bean执行初始化方法之前执行此方法
*/
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
/**
* 在bean执行初始化方法之后执行此方法
*/
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
应用上下文ApplicationContext
应用上下文ApplicationContext是spring中较之于BeanFactory更为先进的IOC容器,ApplicationContext除了拥有BeanFactory的所有功能外,还支持特殊类型bean如上一节中的BeanFactoryPostProcessor和BeanPostProcessor的自动识别、资源加载、容器事件和监听器、国际化支持、单例bean自动初始化等。
BeanFactory是spring的基础设施,面向spring本身;而ApplicationContext面向spring的使用者,应用场合使用ApplicationContext。
bean的生命周期:
XML文件 ---> BeanDefinition ---> BeanFactoryPostProcessor修改BeanDefinition ---> Bean实例化 ---> BeanPostProcessor前置处理 ---> 执行bean的初始化方法 ---> BeanPostProcessor的后置处理 ---> 使用
事件监听
ApplicationContext容器提供了完善的事件发布和事件监听功能。
ApplicationEventMulticaster接口是注册监听器和发布事件的抽象接口,AbstractApplicationContext包含其实现类实例作为其属性,使得ApplicationContext容器具有注册监听器和发布事件的能力。在AbstractApplicationContext#refresh方法中,会实例化ApplicationEventMulticaster、注册监听器并发布容器刷新事件ContextRefreshedEvent;在AbstractApplicationContext#doClose方法中,发布容器关闭事件ContextClosedEvent。
bean的初始化和销毁方法
在spring中,定义bean的初始化和销毁方法有三种方法:
- 在xml文件中制定init-method和destroy-method
- 继承自InitializingBean和DisposableBean
- 在方法上加注解PostConstruct和PreDestroy:通过BeanPostProcessor实现
Aware接口
Aware是感知、意识的意思,Aware接口是标记性接口,其实现子类能感知容器相关的对象。常用的Aware接口有BeanFactoryAware和ApplicationContextAware,分别能让其实现者感知所属的BeanFactory和ApplicationContext。
BeanFactoryAware在bean实例化后,BeanPostProcessor前置处理前进行感知。
ApplicationContextAware在BeanPostProcessor前置处理中进行感知。
bean作用域
每次向容器获取prototype作用域bean时,容器都会创建一个新的实例。
在BeanDefinition中增加描述bean的作用域的字段scope。创建prototype作用域bean时,不往singletonObjects中增加该bean。prototype作用域bean不执行销毁方法。
FactoryBean
FactoryBean是一种特殊的bean,当向容器获取该bean时,容器不是返回其本身,而是返回其FactoryBean#getObject方法的返回值,可通过编码方式定义复杂的bean。
实现逻辑比较简单,当容器发现bean为FactoryBean类型时,调用其getObject方法返回最终bean。当FactoryBean#isSingleton==true,将最终bean放进缓存中,下次从缓存中获取。改动点见AbstractBeanFactory#getBean。