Spring框架(基础篇)IoC篇

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。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值