03Spring底层架构核心概念

Spring底层架构核心概念

BeanDefinition

BeanDefinition表示Bean定义,BeanDefinition中存在很多属性用来描述一个Bean的特点

  • class:表示Bean类型
  • scope:表示Bean的作用域
  • lazyInit:表示Bean是否是懒加载
  • initMethodMethod:表示Bean初始化要执行的方法
  • destoryMethod:表示Bean销毁时要执行的方法

在Spring中,可以通过以下几种方式定义Bean

  • @Bean
  • @Component(@Service、@Controller)

编程式定义Bean

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

// 生成一个BeanDefinition对象,并设置beanClass为User.class,并注册到ApplicationContext中
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(User.class);
context.registerBeanDefinition("user", beanDefinition);

System.out.println(context.getBean("user"));

可以通过设置BeanDefinition设置一个Bean的其他属性

beanDefinition.setScope("prototype"); // 设置作用域
beanDefinition.setInitMethodName("init"); // 设置初始化方法
beanDefinition.setLazyInit(true); // 设置懒加载

BeanDefinitionReader

  • 是一个接口,读取Spring配置文件中的内容,将其转换为IOC容器内部的数据结构:BeanDefinition
AnnotatedBeanDefinitionReader
  • 可以直接将某个类转换为BeanDefinition,并且会解析该类上的注解
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(context);

// 将User.class解析为BeanDefinition
annotatedBeanDefinitionReader.register(User.class);

System.out.println(context.getBean("user"));
  • 它能解析的注解是:@Conditional、@Scope、@Lazy、@Primary、@DependsOn、@Role、@Description
XMlBeanDefinitionReader

可以解析标签

		XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
		int i = xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");
		System.out.println(applicationContext.getBean("user"));
ClassPathBeanDefinitionScanner
  • ClassPathBeanDefinitionScanner是扫描器,但是它的作用和BeanDefinitionReader类似,它可以进行扫描,扫描某个包路径,对扫描到类进行解析,比如,扫描到的类如果存在@Component注解,那么就会把该类解析为一个BeanDefinition
		applicationContext.refresh();
		ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(applicationContext);
		scanner.scan("com.zhouyu");
		System.out.println(applicationContext.getBean("userService"));

BeanFactory

  • 是一个工厂(接口),它负责生产和管理bean的一个工厂。在Spring容器中,BeanFactory是工厂的顶层接口,也是IOC容器的核心接口,一次BeanFactory中定义了管理Bean的通用方方法,如getBean和containsBean等,它的职责包括:实例化、定位、配置应用程序中的对象以及建立这些对象中的依赖。

使用场景:

  • 从IOC容器中获取Bean(byName or byType)
  • 检索IOC容器中是否包含指定的Bean
  • 判断bean是否是单例

ApplicationContext

  • 是一个接口,本质上也是一个BeanFactory
    • HierarchicalBeanFactory:拥有父BeanFactory的功能
    • ListableBeanFactory:拥有获取beanNames的功能
    • ResourcePatternResolver:资源加载器,可以一次性获取多个资源文件(文件资源等)
    • EnvironmentCapable:可以获取运行时环境
    • ApplicationEventPublisher:拥有广播事件的功能
    • MessageSource:拥有国际化的功能
国际化

先定义一个MessageSource

@Bean
public MessageSource messageSource() {
 ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
 messageSource.setBasename("messages");
 return messageSource;
}

使用

context.getMessage("test", null, new Locale("en"))

FactoryBean

  • 能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似

为什么会有FactoryBean?

  • 在某些情况下,实例化Bean过程比较复杂。配置方式的灵活性是受限的,这个时候采用编码的方式可能会得到一个简单的方案。Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过该接口定制实例化Bean的逻辑。
public class Person {

	private String name;

	private Integer age;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Person{" +
				"name='" + name + '\'' +
				", age=" + age +
				'}';
	}
}
@Component
public class MyFactoryBean implements FactoryBean {

	@Override
	public Object getObject() throws Exception {
		Person person = new Person();
		person.setName("Acorn");
		person.setAge(12);
		return person;
	}

	@Override
	public Class getObjectType() {
		return Person.class;
	}

	@Override
	public boolean isSingleton() {
		return FactoryBean.super.isSingleton();
	}
}
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
		Person bean = (Person) applicationContext.getBean("myFactoryBean");
		System.out.println(bean);

		MyFactoryBean bean1 = (MyFactoryBean) applicationContext.getBean("&myFactoryBean");
		System.out.println(bean1);

FactoryBean的使用场景

  • FactoryBean在Spring中最典型的应用就是用用来创建AOP的代理对象
  • AOP实际上是Spring在运行时创建了一个代理对象,也就是说这个对象,是我们在运行时创建的,而不是一开始就定义好的,这很符合工厂方法模式。更形象地说,AOP代理对象通过Java的反射机制,在运行时创建了一个代理对象,在代理对象的目标方法中根据业务要求织入了相应的方法。这个对象在Spring中就是——ProxyFactoryBean

BeanPostProcessor

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

 @Override
 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  if ("userService".equals(beanName)) {
   System.out.println("初始化前");
  }

  return bean;
 }

 @Override
 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  if ("userService".equals(beanName)) {
   System.out.println("初始化后");
  }

  return bean;
 }
}

一个BeanPostProcessor可以在任意一个Bean的初始化前和初始化之后去额外做一些用户自定义的逻辑。

你可能感兴趣的:(Spring,spring)