0
点赞
收藏
分享

微信扫一扫

Spring篇1

凯约 2023-05-11 阅读 64

Applicationcontext与BeanFactory区别

applicationcontext对BeanFactory实现额外增强 1.applicationcontext主动添加Bean(工厂)处理器 来完成扫包2.applicationcontext主动添加bean处理器 ----依赖注入@Autowired 3.applicationcontext主动初始化单例对象BeanFactory----bean定义信息、单例池

Bean工厂处理器与Bean后置处理器之间有哪些区别

1.Bean工厂处理器是在实例化Bean之前执行,例如 Spring中ConfigurationClassPostProcessor 解析 componentScan , Bean , Import ,ImportResource 注册Bean信息,可以通过工厂Bean处理器修改Bean的定义信息。2.Bean后置处理器 是在 init前后执行 ,可以修改Bean对象为代理对象 从而对我们方法实现增强。

SpringBean的生命周期

四阶段:实例化->属性赋值->初始化->销毁


bean定义阶段-BeanDifinition(可单独作为一个章节去了解)
1.元信息配置
面向资源(xml)

xml方式配置、Propeties配置(具体可以细分去了解,相关的定义bean和注册bean)

Spring篇1_bean

public static void main(String[] args) {
	DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
	// 实例化 基于properties资源的 BeanDefinitionReader
	XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
	String location = "/META-INF/dependency-lookup-context.xml";
	// 加载 Properties 文件,用resource的方式可以避免乱码
	// 指定字符编码 UTF-8
	Resource resource = new ClassPathResource(location);
	EncodedResource encodedResource = new EncodedResource(resource, "UTF-8");
	int beanNumbers = beanDefinitionReader.loadBeanDefinitions(encodedResource);
	System.out.printf("已加载的 BeanDefinition 数量: %d%n", beanNumbers);
	// 通过 bean id 和类型进行依赖查找
	User user = beanFactory.getBean("user", User.class);
	System.out.println(user);
    }

Spring篇1_注解_02

public static void main(String[] args) {
  DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
  // 实例化 基于properties资源的 BeanDefinitionReader
  PropertiesBeanDefinitionReader beanDefinitionReader = new PropertiesBeanDefinitionReader(beanFactory);
  String location = "/META-INF/user-bean.properties";
  // 加载 Properties 文件,用resource的方式可以避免乱码
  // 指定字符编码 UTF-8
  Resource resource = new ClassPathResource(location);
  EncodedResource encodedResource = new EncodedResource(resource, "UTF-8");
  int beanNumbers = beanDefinitionReader.loadBeanDefinitions(encodedResource);
  System.out.printf("已加载的 BeanDefinition 数量: %d%n", beanNumbers);
  // 通过 bean id 和类型进行依赖查找
  User user = beanFactory.getBean("user", User.class);
  System.out.println(user);
    }

面向注解
  • @component
  • @import
  • @bean
面向API

命名方式

可以指定bean的名称

BeanDefinitionBuilder#registerBeanDefinition

非命名方式

不指定bean的名称,用spring默认的bean名称生成

BeanDefinitionReaderUtils.registerWithGeneratedName

配置类方式

AnnotatedBeanDefinitionReader.register()

2.元信息解析

针对资源的解析

有两个解析器XmlBeanDefinitionReader和 PropertiesBeanDefinitionReader他们都继承于AbstractBeanDefinitionReader

针对于注解的解析

有AnnotatedBeanDefinitionReader他不继承与任何类,因为注解的扫描和资源的扫描是完全不同的

AnnotationConfigApplicationContext上下文中默认的reader就是AnnotatedBeanDefinitionReader

3.元信息注册

Spring篇1_注解_03

核心代码

@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		Assert.hasText(beanName, "Bean name must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");

		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				// 这里会对MethodOverrides做检查
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}
		// 判断是否有同名的bean被注册过了
		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
		// 是否允许直接进行负载
		if (existingDefinition != null) {
			if (!isAllowBeanDefinitionOverriding()) {
				throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
			}
			else if (existingDefinition.getRole() < beanDefinition.getRole()) {
				// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
				if (logger.isInfoEnabled()) {
					logger.info("Overriding user-defined bean definition for bean '" + beanName +
							"' with a framework-generated bean definition: replacing [" +
							existingDefinition + "] with [" + beanDefinition + "]");
				}
			}
			else if (!beanDefinition.equals(existingDefinition)) {
				if (logger.isDebugEnabled()) {
					logger.debug("Overriding bean definition for bean '" + beanName +
							"' with a different definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			else {
				if (logger.isTraceEnabled()) {
					logger.trace("Overriding bean definition for bean '" + beanName +
							"' with an equivalent definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		else {
			if (hasBeanCreationStarted()) {
				// Cannot modify startup-time collection elements anymore (for stable iteration)
				// 因为beanDefinitionMap是全局变量,这里定会存在并发访问的情况
				synchronized (this.beanDefinitionMap) {
					this.beanDefinitionMap.put(beanName, beanDefinition);
					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
					removeManualSingletonName(beanName);
				}
			}
			else {
				// Still in startup registration phase
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				removeManualSingletonName(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

		if (existingDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
	}

4.元信息合并

基本解答

1.首先是实例化Bean,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚末初始化的依赖时,容器就会调用doCreateBean()方法进行实例化,实际上就是通过反射的方式创建出一个bean对象

2.Bean实例创建出来后,接着就是给这个Bean对象进行属性填充,也就是注入这个Bean依赖的其它bean对象

属性填充完成后,进行初始化Bean操作,初始化阶段又可以分为几个步骤:

3.1执行Aware接口的方法

3.2.Spring会检测该对象是否实现了xxxAware接口,通过Aware类型的接口,可以让我们拿到Spring容器的些资源。如实现

3.3.BeanNameAware接口可以获取到BeanName,实现BeanFactoryAware接口可以获取到工厂对象BeanFactory等

3.4.执行BeanPostProcessor的前置处理方法postProcessBeforelnitialization(),对Bean进行一些自定义的前置处理

3.5.判断Bean是否实现了InitializingBean接口,如果实现了,将会执行lnitializingBean的afeterPropertiesSet()初始化方法;

3.6.执行用户自定义的初始化方法,如init-method等;

3.7.执行BeanPostProcessor的后置处理方法postProcessAfterinitialization()

初始化完成后,Bean就成功创建了,之后就可以使用这个Bean, 当Bean不再需要时,会进行销毁操作,

3.8首先判断Bean是否实现了DestructionAwareBeanPostProcessor接口,如果实现了,则会执行DestructionAwareBeanPostProcessor后置处理器的销毁回调方法

3.8其次会判断Bean是否实现了DisposableBean接口,如果实现了将会调用其实现的destroy()方法

3.9最后判断这个Bean是否配置了dlestroy-method等自定义的销毁方法,如果有的话,则会自动调用其配置的销毁方法;

Spring相关注解

@Controller - 用于 Spring MVC 项目中的控制器类。

@Service - 用于服务类。

@RequestMapping - 用于在控制器处理程序方法中配置 URI 映射。

@ResponseBody - 用于发送 Object 作为响应,通常用于发送 XML 或 JSON 数据作为响应。

@PathVariable - 用于将动态值从 URI 映射到处理程序方法参数。

@Autowired - 用于在 spring bean 中自动装配依赖项。

@Qualifier - 结合@Autowired 注解一起使用,以避免在存在多个 bean 类型实例时出现混淆。

而在@Autowired注解中加入(required = false)属性后,表示该注入是可选的。如果当前上下文中没有找到与要求匹配的Bean,则不会抛出异常,而只是简单地跳过这个注入。这样可以避免由于缺少某些Bean导致应用程序启动失败的情况发生。
需要注意的是,当设置(required = false)属性后,如果没有找到匹配的Bean,则被注入的字段、构造函数或方法参数会被设置为null。因此,在使用这个属性时,需要确保代码对这种情况进行了处理,以避免空指针异常等运行时错误的发生。
@Autowired(required = false)
private Date date ;
@Autowired
@Qualifier("birth")
private Date birthday ;

@Scope - 用于配置 spring bean 的范围。

@Scope("singleton"):默认值为singleton,表示在整个应用程序中只创建一个Bean实例。适用于无状态的Bean,例如工具类。

@Scope("prototype"):每次请求都会创建一个新的Bean实例。适用于有状态的Bean,例如用户登录信息等。

@Scope("session"):在用户会话期间只创建一个Bean实例,不同用户之间的Bean实例是独立的。适用于需要保存用户状态的Bean,例如购物车。

@Scope("request"):在HTTP请求期间只创建一个Bean实例,不同请求之间的Bean实例是独立的。适用于需要处理HTTP请求的Bean,例如REST API。

@Scope("globalSession"):在全局会话期间只创建一个Bean实例,通常用于基于Portlet的Web应用程序。

@Configuration,@ComponentScan 和 @Bean - 用于基于 java 的配置。 在下面的示例中,@ComponentScan注解指定了需要扫描的两个包路径,即"com.example.package1"和"com.example.package2"。Spring会扫描这两个包下的所有组件,并将其作为bean注册到应用程序上下文中。

此外,@ComponentScan注解也可以与其他注解一起使用,如@EnableAutoConfiguration注解和@SpringBootApplcation注解。

@Configuration
@ComponentScan(basePackages = {"com.example.package1", "com.example.package2"})
public class AppConfig {
  // 配置bean
}

@Aspect,@Before,@After,@Around,@Pointcut - 用于切面编程(AOP)。

举报

相关推荐

0 条评论