Spring-IOC/AOP

本文是根据JavaGuide的总结复习

SpringIOC/AOP

    • 什么是Spring IOC?
    • Spring IOC初始化过程
    • 什么是Bean
    • 什么是AOP,AOP的作用以及实现
    • Spring AOP和AspcetJ AOP的区别
    • Spring Bean的作用域
    • Spring单例Bean的线程安全问题
    • @Component 和 @Bean 的区别是什么?
    • Bean的生命周期
    • SpringMVC是什么?
    • SpringMVC的执行流程
    • Spring中用到的设计模式
    • Spring中的事务的管理方式
    • Spring中的事务隔离级别
    • Spring中的事务传播
    • @Transactional(rollbackFor = Exception.class)注解了解吗?
    • JPA是什么?
    • 使用JPA在数据库中非持久化一个字段

什么是Spring IOC?

IOC控制反转,其实是设计模式中的依赖倒置思想的实现,将原本在程序中手动创建对象的控制权交给Spring框架来管理。
Spring-IOC/AOP_第1张图片
依赖注入:把底层类作为参数传入上层类,实现上层类对下层类的“控制”。

图片于来源:网络

Spring IOC初始化过程

Spring-IOC/AOP_第2张图片
(1)首先通过ClassPathXmlApplicationContext获取到所提供的资源文件路径,处理成配置文件数组
(2)调用Refresh方法进行容器的重建。Refresh会将原本的Applicationontext销毁。
(3)在Refresh方法中:

  • 首先进行创建Bean容器前的准备工作,调用prepareRefrash()方法。记录启动时间,校验xml文件。
  • 创建Bean容器,加载并注册Bean,使用的是**obtainFreshBeanFactory()方法。在这个方法中会进行初始化BeanFactory加载Bean,注册Bean**等工作。但是在这里Bean实例还没有被创建。

ApplicationContext 继承自 BeanFactory但是它不应该被理解为 BeanFactory 的实现类而是说其内部持有一个实例化的 BeanFactory(DefaultListableBeanFactory)。以后所有的 BeanFactory 相关的操作其实是委托给这个DefaultListableBeanFactory实例来处理的。

什么是Bean

从代码层面来讲,就是接口BeanDefinition的实例。

什么是AOP,AOP的作用以及实现

AOP就是面向切面编程的意思,能够将那些与业务无关,却为业务模块所共同调用的逻辑和责任封装起来。(如:事务处理,日志管理,权限控制等)。便于减少代码重复,降低模块的耦合度,利于扩展性和可维护性。
SpringAOP基于动态代理。

  • 如果实现了某个接口,那么SpringAOP使用JDK Proxy去创建代理对象。
  • 如果没有实现接口的对象,使用Cglib去生产一个代理对象的子类作为代理。
  • 也可以使用AspectJ。AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了

Spring AOP和AspcetJ AOP的区别

  • Spring AOP是运行是增强,而AspectJ是编译时增强。
  • Spring AOP基于代理,而AspectJ基于字节码操作。
  • SpringAOP中集成了AspectJ,当切面很多的时候推荐使用AspectJ

Spring Bean的作用域

  • singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的。
  • prototype : 每次请求都会创建一个新的 bean 实例。
  • request : 每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。
  • session : 每一次HTTP请求都会产生一个新的 bean,该bean仅在当前 HTTP session 内有效。
  • global-session: 全局session作用域,仅仅在基于portlet的web应用中才有意义,Spring5已经没有了。

Spring单例Bean的线程安全问题

单例Bean是存在线程安全问题的。当多个线程操作同一个对象的非静态成员变量时,就会产生线程安全问题。
解决方法:使用ThreadLocal定义成员变量。

@Component 和 @Bean 的区别是什么?

  • 作用对象不同:@Component作用于类,而@Bean作用于方法。
  • @Component结合@ComponentScan可以很方便的将类装配到Bean容器中。
  • @Bean 注解通常是我们在标有该注解的方法中定义产生这个bean的实例,@Bean告诉了Spring这是某个类的示例,当我需要用它的时候还给我。
  • 当引入第三方插件或者库需要用@Bean装入Spring容器管理,使用@component不能实现。

Bean的生命周期

Spring-IOC/AOP_第3张图片

SpringMVC是什么?

MVC是一种设计模式,Spring MVC是Spring框架对于MVC模式的运用。SpringMVC主要用于帮助我们进行web开发。MVC模式下,将后端分为了Service层处理业务,Dao层数据库操作,Entity层实体类,Controller层,返回数据给前台。

SpringMVC的执行流程

Spring-IOC/AOP_第4张图片

  1. 客户端发送请求,请求到DispatcherServlet
  2. DispatcherServlet根据请求信息调用的HandlerMapping,解析请求对应的Handler
  3. 解析对应的Handler(Controller控制器)以后,开始由HandlerAdapter,适配器来进行处理。
  4. HandlerAdapter根据Handler来调用真正的处理器处理请求,和相应的逻辑业务。
  5. 处理器处理完后,返回一个ModelandView对象,Model返回数据对象,View是逻辑上的View。并不是真正展示的视图
  6. ViewResolver根据返回的View查找实际的View。
  7. DispaterServlet把返回Model传给View视图渲染
  8. 返回View给客户端

Spring中用到的设计模式

  • 工厂模式:
    Spring使用工厂模式可以通过 BeanFactory 或 ApplicationContext 创建 bean 对象。
    BeanFactory:延迟注入,使用到某个bean的时候才会进行创建。
    ApplicationContext:容器启动时,一次性全部创建bean
  • 单例模式
    Spring中的Bean的默认作用域就是singleton。
    Bean的作用域还有:
    Spring-IOC/AOP_第5张图片
    Spring实现单例模式的方式
    通过ConcurrentHashMap实现单例注册表的方式实现单例模式。
    // 通过 ConcurrentHashMap(线程安全) 实现单例注册表
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "'beanName' must not be null");
        synchronized (this.singletonObjects) {
            // 检查缓存中是否存在实例  
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                //...省略了很多代码
                try {
                    singletonObject = singletonFactory.getObject();
                }
                //...省略了很多代码
                // 如果实例对象在不存在,我们注册到单例注册表中。
                addSingleton(beanName, singletonObject);
            }
            return (singletonObject != NULL_OBJECT ? singletonObject : null);
        }
    }
    //将对象添加到单例注册表
    protected void addSingleton(String beanName, Object singletonObject) {
            synchronized (this.singletonObjects) {
                this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));

            }
        }
}
  • 代理模式
    SpringAOP就是基于代理模式的。
    如果代理对象实现了某个接口就是用JDK Proxy去创建代理对象。
    如果代理对象没有实现某个接口,就会使用Cglib去生成一个被代理对象实例来进行代理。
    Spring中的代理也可以使用AspectJ进行,Spring集成了AspectJ。当切面多的时候就可以使用它。
  • 模板方法:是一种行为设计模式,它定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。
    在Spring中的模板方法使用主要是体现在以Template结尾的数据库操作类中,如JDBCTemplate,HiberbateTemplate
    但Spring中对于模板方法模式进行了改进,一般的模板方法都是使用的子类去实现一个操作,而Spring中则是采用Callback模式(回调模式)和模板方法配合使用。
    Callback模式(回调模式):把工作流内的某个功能,按照约定的接口暴露给外部使用者,为外部使用者提供数据,或要求外部使用者提供数据。
  • 观察者模式:是一种对象行为型模式。它表示的是一种对象与对象之间具有依赖关系,当一个对象发生改变的时候,这个对象所依赖的对象也会做出反应。
    Spring中的事件驱动模型就是用来这个设计模式。
    Spring事件执行流程如下:
    (1) 定义一个事件: 实现一个继承自 ApplicationEvent,并且写相应的构造函数;
    (2)定义一个事件监听者:实现 ApplicationListener 接口重写 onApplicationEvent() 方法
    (3)使用事件发布者发布消息: 可以通过 ApplicationEventPublisher 的 publishEvent() 方法发布消息
  • 适配器模式:适配器模式(Adapter Pattern) 将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。
    SpringAOP的增强或者通知都使用了适配器模式,相关的接口:AdvisorAdapter。
    Spring预定义的通知要通过对应的适配器,适配成 MethodInterceptor接口(方法拦截器)类型的对象(如:MethodBeforeAdviceInterceptor 负责适配 MethodBeforeAdvice)。
  • SpringMVC中的适配器模式:
    DispatcherServlet 根据请求信息调用 HandlerMapping,解析请求对应的 Handler。解析到对应的 Handler(也就是我们平常说的 Controller 控制器)后,开始由HandlerAdapter 适配器处理。

-装饰者模式(包装器模式):动态地给对象添加一些额外的属性或行为
Spring 中配置 DataSource 的时候,DataSource 可能是不同的数据库和数据源。这个时候就要用到装饰者模式(这一点我自己还没太理解具体原理)。Spring 中用到的包装器模式在类名上含有 Wrapper或者 Decorator。这些类基本上都是动态地给一个对象添加额外的职责。

  • Spring中用到的设计模式:
  • 在Spring IOC中,Spring在beanFactory和ApplicationContext中通过工厂模式创建bean对象。
  • 代理模式:SpringAOP基于代理模式。
  • 适配器模式:SpringAOP的增加或通知使用了适配器模式。SpringMVC中也是用到了适配器模式。(HandlerAdapter)
  • 观察者模式:spring的事件模型使用了观察者模式
  • 包装器模式:Spring中的DataSource使用了包装器模式动态的给类添加职责。
  • 模板方法模式:在Spring中以template结尾的都使用了模板方法模式。如JDBCTemplate

Spring中的事务的管理方式

  1. 编程式事务,在代码中硬编码的。
  2. 声明式事务,在配置文件中配置。推荐的使用方式。

声明式事务分为:
XML
注解

Spring中的事务隔离级别

  • TransactionDefinition 接口中定义了五个表示隔离级别的常量:

TransactionDefinition.ISOLATION_DEFAULT: 使用后端数据库默认的隔离级别,Mysql 默认采用的 REPEATABLE_READ隔离级别 Oracle 默认采用的 READ_COMMITTED隔离级别.

TransactionDefinition.ISOLATION_READ_UNCOMMITTED: 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读

TransactionDefinition.ISOLATION_READ_COMMITTED: 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生

TransactionDefinition.ISOLATION_REPEATABLE_READ: 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。

TransactionDefinition.ISOLATION_SERIALIZABLE: 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

Spring中的事务传播

  • 支持当前事务的情况:

TransactionDefinition.PROPAGATION_REQUIRED(propagation required): 如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。

TransactionDefinition.PROPAGATION_SUPPORTS(propagation supports): 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。

TransactionDefinition.PROPAGATION_MANDATORY(propagation mandatory): 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)

  • 不支持当前事务

TransactionDefinition.PROPAGATION_REQUIRES_NEW: 创建一个新的事务,如果当前存在事务,则把当前事务挂起。

TransactionDefinition.PROPAGATION_NOT_SUPPORTED: 以非事务方式运行,如果当前存在事务,则把当前事务挂起。

TransactionDefinition.PROPAGATION_NEVER: 以非事务方式运行,如果当前存在事务,则抛出异常。

  • 其他情况:

TransactionDefinition.PROPAGATION_NESTED: 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。创建一个新的事务

@Transactional(rollbackFor = Exception.class)注解了解吗?

当@Transactional注解作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。如果类或者方法加了这个注解,那么这个类里面的方法抛出异常,就会回滚,数据库里面的数据也会回滚。

在@Transactional注解中如果不配置rollbackFor属性,那么事物只会在遇到RuntimeException的时候才会回滚,加上rollbackFor=Exception.class,可以让事物在遇到非运行时异常时也回滚。

JPA是什么?

JPA(java persistence API)用于管理JavaEE和JavaSE环境中的持久化,以及对象/关系映射的JavaAPI
是处理数据持久化的一个接口,规范

  1. 实体(pojo)表示关系数据库中的一个表
  2. 每个实体实例对应着该表中的一行
  3. 类必须用javax.persistence.Entity注解
    类必须含有一个public或者protected的无参构造函数
  4. 当实体实例被当做值以分离对象的方式进行传递(例如通过会话bean的远程业务接口)则该类必须实现Serializable(序列化)接口
  5. 唯一的对象标志符,简单主键(javax.persistence.Id),复合主键(javax.persistence.EmbeddledId和javax.persistence.IdClass)

使用JPA在数据库中非持久化一个字段

  • 改变静态修饰static
  • 改变成final修饰
  • transient修饰
  • @Transient注解修饰

你可能感兴趣的:(Spring)