spring底层框架知识总结

目录

1、spring的原理结构

 

 

9、什么是控制反转(ioc),别名依赖注入

9、什么是Spring IOC 容器?

10、Beanfactory和 Application contexts  有什么区别?

 

12、解释Spring支持的几种bean的作用域

13、Spring框架中的单例bean是线程安全的吗?

14、bean的生命周期

15、注解装配(@Required  注解、@Autowired 注解、@Qualifier 注解)

16、spring中bean解决循环依赖

解决办法

17、Spring的MVC框架

18、spring中使用的设计模式


1、spring的原理结构

aop技术

Spring中AOP技术是设计模式中的动态代理模式。只需实现jdk提供的动态代理接口InvocationHandler,所有被代理对象的方法都由InvocationHandler接管实际的处理任务。

9、什么是控制反转(ioc),别名依赖注入

Spring中IOC则利用了Java强大的反射机制来实现。所谓依赖注入即组件之间的依赖关系由容器在运行期决定。其中依赖注入的方法有两种,通过构造函数注入,通过set方法进行注入。

9、什么是Spring IOC 容器?

Spring IOC 容器管理bean对象的整个生命周期。其底层通过concurrenthashmap来存放bean。

10、Beanfactory和 Application contexts  有什么区别?

BeanFactory:

是Spring里面最低层的接口,提供了最简单的容器的功能,只提供了实例化对象和拿对象的功能;

BeanFactory在启动的时候不会去实例化Bean,中有从容器中拿Bean的时候才会去实例化;

ApplicationContext:

应用上下文,继承BeanFactory接口,它是Spring的一各更高级的容器

ApplicationContext在启动的时候就把所有的Bean全部实例化了。

具体实现(ClassPathXmlApplicationContext)

 

12、解释Spring支持的几种bean的作用域

Spring框架支持以下五种bean的作用域:

  • singleton : bean在每个Spring ioc 容器中只有一个实例(默认)。

  • prototype:一个bean的定义可以有多个实例。

  • request:每次http请求都会创建一个bean,该作用域仅在基于web的Spring ApplicationContext情形下有效。

  • session:在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。

  • global-session:在一个全局的HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。

13、Spring框架中的单例bean是线程安全的吗?

不,Spring框架中的单例bean不是线程安全的。但是bean基本上都是用来实现依赖注入,不存在修改操作,所以相对来说不存在线程不安全问题。

为什么bean是单例的?

只在初始化的时候实例化一次,提高效率;

减少了内存开销

14、bean的生命周期

对象的生命周期:创建(实例化-初始化)-使用-销毁,Spring提供了许多对外接口,允许开发者对这三个过程(实例化、初始化、销毁)的前后做一些操作。 
在Spring Bean中,实例化是为bean对象开辟空间(具体可以理解为构造函数的调用),初始化则是对属性的初始化,也就是属性注入(构造函数也可以有属性的初始化语句,但不属于这一部分),而属性注入是通过setter方法注入属性(不管是注解方式还是bean配置property属性方式,其实质都是通过属性的setter方法实现的)。

15、注解装配(@Required  注解、@Autowired 注解、@Qualifier 注解)

@Required  注解:指定具体的bean的id(byname),进行装配注入

@Autowired 注解:根据类型自动装配(bytype)

@Qualifier 注解:与@Autowired 注解一同使用,避免混淆的bean

16、spring中bean解决循环依赖

依赖注入稍不注意就会出现循环依赖:
Bean之间的依赖顺序: BeanA -> BeanB -> BeanA
举个例子:

@Component
public class CircularDependencyA {
 
    private CircularDependencyB circB;
 
    @Autowired
    public CircularDependencyA(CircularDependencyB circB) {
        this.circB = circB;
    }
}
@Component
public class CircularDependencyB {
 
    private CircularDependencyA circA;
 
    @Autowired
    public CircularDependencyB(CircularDependencyA circA) {
        this.circA = circA;
    }
}

运行SpringBootApplication:

@SpringBootApplication
@ComponentScan("com.example.circulardependency.constructor")
public class CirculardependencyApplication {

    public static void main(String[] args) {
        SpringApplication.run(CirculardependencyApplication.class, args);
    }
}

报错

BeanCurrentlyInCreationException: Error creating bean with name 'circularDependencyA': Requested bean is currently in creation: Is there an unresolvable circular reference?

解决办法

出现循环依赖是因为设计问题,最佳处理方法是重新设计

在实际开发中,推倒重来往往是不允许的,所以会有以下几种补救方法。

1.改用setter注入方式(推荐)

与constructor注入不同,setter是按需注入的,并且允许依赖对象为null;

@Component
public class CircularDependencyA {
 
    private CircularDependencyB circB;
 
    @Autowired
    public void setCircB(CircularDependencyB circB) {
        this.circB = circB;
    }
 
    public CircularDependencyB getCircB() {
        return circB;
    }
}
@Component
public class CircularDependencyB {
 
    private CircularDependencyA circA;
 
    private String message = "Hi!";
 
    @Autowired
    public void setCircA(CircularDependencyA circA) {
        this.circA = circA;
    }
 
    public String getMessage() {
        return message;
    }
}

添加单元测试:

@RunWith(SpringRunner.class)
@SpringBootTest
@ComponentScan("com.example.circulardependency.setter")
public class CirculardependencyApplicationTests {
    @Bean
    public CircularDependencyB getDependencyB() {
        return new CircularDependencyB();
    }

    @Bean
    public CircularDependencyA getDependencyA() {
        CircularDependencyA circularDependencyA = new CircularDependencyA();
        circularDependencyA.setCircularDependencyB(getDependencyB());
        return circularDependencyA;
    }

    @Test
    public void contextLoads() {
        System.out.println("Hello world.");
        CircularDependencyA circularDependencyA = getDependencyA();
        System.out.println(circularDependencyA.getCircularDependencyB().getMessage());
    }
}

2. @Lazy注解

@Lazy延迟初始化。在本例中,会先构建 CircularDependencyA完成后, 再构建CircularDependencyB,打破dependency circle。

@Component
public class CircularDependencyA {
 
    private CircularDependencyB circB;
 
    @Autowired
    public CircularDependencyA(@Lazy CircularDependencyB circB) {
        this.circB = circB;
    }
}

3. 使用ApplicationContextAware, InitializingBean

ApplicationContextAware获取SpringContext,用于加载bean;InitializingBean定义了设置Bean的property之后的动作。

@Component
public class CircularDependencyA implements InitializingBean, ApplicationContextAware {
    private CircularDependencyB circB;
    private ApplicationContext context;
    
    @Override
    public void afterPropertiesSet() throws Exception {
        this.circB = context.getBean(CircularDependencyB.class);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
    }

    public CircularDependencyB getCircularDependencyB() {
        return circB;
    }
}

原理:跟Spring Bean的Life cycle有关:先实例化,再调用setApplicationContext(), afterPropertiesSet(); 所以,CircularDependencyB已经加载完毕后,再加载CircularDependencyA。
倘若,CircularDependencyA先实例化, 调用afterPropertiesSet()时发现CircularDependencyB尚未加载,先加载CircularDependencyB(调用构造函数,由于此时CircularDependencyA已经实例化了,所以能够顺利加载),设置属性circB,CircularDependencyA加载完成。
 

17、Spring的MVC框架

处理前台与后台数据页面请求

18、spring中使用的设计模式

https://blog.csdn.net/Dwade_mia/article/details/78883045

发布了468 篇原创文章 · 获赞 95 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/qq_37909508/article/details/100048645