您的位置:首页 > 文旅 > 美景 > 网站推广方案的构成_手机网址制作_网站一级域名和二级域名_海外推广方法有哪些

网站推广方案的构成_手机网址制作_网站一级域名和二级域名_海外推广方法有哪些

2025/3/29 16:35:34 来源:https://blog.csdn.net/qq_25308331/article/details/146459081  浏览:    关键词:网站推广方案的构成_手机网址制作_网站一级域名和二级域名_海外推广方法有哪些
网站推广方案的构成_手机网址制作_网站一级域名和二级域名_海外推广方法有哪些

IoC,Inversion of Control 控制反转,将原本由应用程序负责对象创建的工作,交给IOC容器来完成。容器通过依赖注入(DI,Dependency Injection)来实现。

作用:降低类对象之间的耦合度,减少代码量。

1 Ioc 容器

图 IoC容器的工作流程

  1. 定义Bean:通过XML、Java注解或Java配置类来定义。
  2. 解析与存储BeanDefinition:容器读取Bean的配置,解析为BeanDefinition对象,存储到BeanFactory中。
  3. 创建Bean:根据BeanDefinition创建Bean实例,注入Bean的依赖。
  4. 调用生命周期方法:Bean初始化时会调用这个Bean实现的初始化方法(如@PostConstruct)。容器关闭时会调用Bean实现的销毁方法(如@PreDestory)。

BeanFactory 是提供了管理Bean方法的接口。ApplicationContext继承了BeanFactory接口,并做了扩展:1)集成AOP。2)国际化。3)事件发布。4)资源加载ResourceLoader。

2 定义Bean

Bean是由Ioc容器管理的对象。

singleton

单例,默认。同一个容器只有一个实例,不同容器生成不同的bean实例。

prototype

不同bean依赖的bean会被创建不同的实例。

request

每个请求都会创建不同的bean。

session

每个session都会创建不同的bean。

application

每个servletContext生成不同的bean。

websocket

每个socket连接生成不同的bean。

表 Bean的作用域

定义方式

优点

缺点

XML

易于阅读和编辑,可扩展性强。

不够简洁,代码耦合度高。

注解

简洁易读,易于维护。

破坏了类的纯洁性,不易调试。

表 XML与注解形式定义Bean的优缺点

3 解析

容器从XML或注解中读取Bean的配置信息,并将其转换成BeanDefinition对象。

BeanDefinitionReader是定义了读取Bean配置方法的接口,XmlBeanDefinitionReader是其一个实现类,用于解析并读取XML配置的Bean信息。

容器会将BeanDefinition对象存储到容器的注册表中,为后续Bean的实例化和依赖注入提供依据。

4 Bean的实例化

构造器注入

推荐首选方式,通过构造函数传递依赖项。依赖不可变。

Setter方法注入

通过Setter方法设置依赖项,适用可选依赖或需要重新配置的依赖。

字段注入

不推荐,直接通过字段注入依赖项(@Autowired直接加在字段上面)。

表 Bean的依赖注入方式

4.1 循环依赖及三级缓存

循环依赖是指有两个bean,它们有字段互相指向对方。构造器注入在面对循环依赖时会在项目启动时抛错。而字段注入依靠“三级缓存”技术则解决了这个问题。

三级缓存通过提前暴露Bean的早期引用,来打破循环依赖的死锁。

三级缓存

存储Bean的工厂对象(ObjectFacotry)。

二级缓存

存储由三级缓存提供的工厂对象实例化的Bean,此时还未完成依赖注入。

一级缓存

存储完全初始化好的单例Bean。

表 三级缓存的组成

循环依赖解决流程如下(以Bean A 依赖Bean B,B依赖A为例):

1)创建Bean A。
a)实例化A,获得A的原始对象(通过反射调用无参构造器)。
b)将A的工作对象放入三级缓存中。
addSingletonFactory(beanNameA,() -> getEarlyBeanReference(beanNameA,mdb,beanA));
c)填充A的属性,发现A依赖Bean B,触发Bean B的创建。
2)创建Bean B。
前两步同Bean A的创建,然后再填充B的属性,发现B依赖A,触发Bean A的获取。
3)解决B对A的依赖。
a)从一级缓存获取A,未找到。
b)从二级缓存获取A,未找到。
c)从三级缓存获取A的工厂对象,找到并调用其getObject()生成A的早期引用。
d)将A的早期引用存入二级缓存,并从三级缓存移除A的工厂对象。
e)将A到早期引用注入到B中。
f)完成Bean B的初始化,并将其放入一级缓存。
4)完成A的初始化。
a)将Bean B的引用注入到A中。
b)完成Bean A的初始化,将A放入一级缓存,并从二级缓存移除。

4.1.1 工厂对象ObjectFactory

@FunctionalInterface
public interface ObjectFactory<T> {T getObject() throws BeansException;
}

通过getObject()方法延迟生成或获取一个对象。(@FunctionalInterface 是一个函数式接口,可通过Lambda表达式实现。),有以下作用:

  1. 延迟创建对象,只有在调用getObject() 是才会实际生成或获取对象。
  2. 处理代理逻辑,如AOP增强Bean。
  3. 解耦实例化过程:将对象生成逻辑封装在工厂中,避免直接暴露未完成的Bean。

4.1.2 第二级缓存的必要性

第二级缓存用于隔离“完全初始化”和“未完全初始化”的Bean。确保外部组件只能获取完全初始化的Bean(只能通过一级缓存),而二级缓存仅用于内部依赖注入。

4.2 字段注入的缺陷

1)破坏了封装性,直接注入私有字段,绕过构造器及Setters,通过反射注入。违反了面向对象的设计原则。

2)循环依赖的潜在风险。

3)字段注入的依赖可变,而构造器注入的依赖是final的。

5 生命周期

当容器初始化bean后会调用bean实现的InitializingBean接口的afterPropertiesSeet()方法,当容器销毁时,会调用bean实现的DisposableBean接口的destory()方法。

BeanPostProcessor接口提供了可以覆盖容器实例化逻辑或依赖逻辑的方法。bean 先由容器实例化,然后由BeanPostProcessor进行操作。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com