spring 简答

5/14/2021

# spring

# 整体架构

# foo

# 核心容器

Beans,创建和管理bean以及ioc,访问配置文件等

  • ioc:即控制反转。解释“构成应用程序主干并由springioc容器管理的对象成为bean。 bean是由springioc容器实例化,组装和管理的对象,他们是springioc容器的基础。
  • DI:即依赖注入(应用依赖于ioc容器,ioc容器把小的外部资源注入进应用依赖的某个对象。)
  • Core,核心工具类,是其它组件的基本核心,我们也可以自己使用。
  • Context,构建于core和beans模块基础之上,为spring核心提供扩展,它的关键是ApplicationContext接口,添加了bean的生命周期控制等功能。
  • Expression Language, 提供强大的表达式语言,用于在运行时查询和操纵对象。

# 依赖注入

  • 定义 依赖注入 指程序运行过程中,如果需要调用另一个对象协助时,无须在代码中创建被调用者,而是依赖于外部的注入。
  1. 构造方法注入

    • 优点
      • 脱离了ioc框架这个类仍然可以工作(POJO)
    • 缺点
      • 参数过多
      • 一旦是用构造函数注入,就无法是用默认构造函数(比如MVC框架的Controller类)
      • 有冗余方法并不需要依赖
         public class StupidStudent {
             private SmartStudent smartStudent;
             public StupidStudent(SmartStudent smartStudent) {
                 this.smartStudent = smartStudent;
             }
             public doHomewrok() {
                 smartStudent.doHomework();
                 System.out.println("学渣抄作业");
             }
         }
         public class StudentTest {
             public static void main(String[] args) {
                 SmartStudent smartStudent = new SmartStudent();
                 StupidStudent stupidStudent = new StupidStudent(smartStudent);
                 stupidStudent.doHomework();
             }
         } 
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
  2. setter方法注入

    • 优点
      • 在对象的生命周期内,可以动态改变依赖,灵活。
    • 缺点
      • 不直观
      public class StupidStudent {
          private SmartStudent smartStudent;
          //添加setter方法
          public void setSmartStudent(SmartStudent smartStudent) {
             this.smartStudent = smartStudent;
          }
          public doHomewrok() {
              smartStudent.doHomework();
              System.out.println("学渣抄作业");
          }
      }
     public class StudentTest {
         public static void main(String[] args) {
             SmartStudent smartStudent = new SmartStudent();
             StupidStudent stupidStudent = new StupidStudent();
             stupidStudent.setSmartStudent(smartStudent);
             stupidStudent.doHomework();
             }
     }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
  3. 接口注入

    • 优点
      • 灵活
    • 缺点
      • 参数过多
      • 新加入依赖时会破坏原有方法名
      public class MovieRecommender {
           private MovieCatalog movieCatalog;
           private CustomerPreferenceDao customerPreferenceDao;
           @Autowired
           public void prepare(MovieCatalog movieCatalog,
           CustomerPreferenceDao customerPreferenceDao) {
               this.movieCatalog = movieCatalog;
               this.customerPreferenceDao = customerPreferenceDao;
           }
        // ...
        }
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

# 封装模块

  • jdbc,用jdbc数据访问进行封装类
  • orm,对象-关系映射api
  • oxm, 对object/xml映射实现抽象层
  • jms, messagingService制造和消费信息的特性
  • Transaction, 支持变成和声明性的事务管理

# AOP

  • AOP实现策略:

    • JavaSE动态代理
    • 字节码生成(cglib)
    • 定制的类加载器
    • 代码生成
    • 语言扩展
  • aop核心,面向切面

  • aspects, 用AspectJ框架

  • instructment, 可以通过代理类在运行时修改的字节,从而改变一个类的功能,实现AOP

  • 三种织入方式

    1. 编译器织入 -- 要有特殊java编译器
    2. 类装载期织入 -- 要有特殊类装载器
    3. 动态代理织入 -- 在运行期间为目标添加通知生成子类 tips:Spring AOP框架默认动态代理织入,而AspectJ采用编译器和类装载期织入
  • Spring AOP增强类型:

    • 前置增强
    • 后置增强:无论方法是正常执行完还是抛出异常都会执行此增强
    • 返回后增强
    • 抛出异常后增强
    • 环绕增强:包围连接点方法的增强,可替代前述任何一种增强
    • 引介增强:能使目标类实现某个接口

# ✨书本上的课后习题(个人觉得有意义/不会的)

  1. 控制反转(IOC)和依赖注入(DI)是什么?优点?

    • ioc是一种设计思想,意味着将设计好的对象给容器控制,非直接由对象控制。
    • Spring中实现控制反转的是IoC容器,其实现方法是依赖注入。
    • 优点 解耦手段。
  2. IOC容器的实现方式有哪些?

    • 构造方法注入
      private TestDIDaoo testDIDaoo;
      public TestDiServiceImpl(TestDao) {
        super();
        this.testDiDao = testDIDaoo;
      }
      //配置
      <bean id="myTestDIDao" class="dao.TestDIDaoImpl" />
      <bean id="testDIService" class="service.TestDIServiceImpl">
        <constructor-arg index="0" ref="myTestDIDao">
      </bean>
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
    • setter注入
       private TestDIDao testDDIDao;
       public void setTestDIDao(TestDIDao testDIDao) {
           this.testDIDao = testDIDao;
       }
       //配置
       <bean id="testDIServicel" class="serice.TestDIServiceImpl1">
           <property name="testDIDao" ></property>
       </bean>
      
      1
      2
      3
      4
      5
      6
      7
      8
      *** 注 spring的依赖注入都是通过反射机制实现。
  3. bean实例化的常见方法?(第三章)

    • 构造方法实例化
    • 静态工厂实例化
    • 实例工厂实例化
  4. 简述基于注解的装配方式的装配方法

    • 1创建bean实现类
    @Conponent()
    public class AnnotationUser {
        @Value("chenheng")
        private String uname;
    }
    
    1
    2
    3
    4
    5
    • 2配置注解
    //配置注解
    <context:component-scan base-package="bean所在的包路径">
    
    1
    2
    • 3测试实例
    main{
        ApplicationContext appCon = new ClassPathXmlApplicationContext("annotationContext.xml");
        AnnotationUser au = (AnnotationUser)appCon.getBean("annotationUser");
        Sysout(au.getUname());
    }
    
    1
    2
    3
    4
    5
  5. @Autowired和@Resource的区别?

    • auto的默认是byType,但当byType有多个时,会用byName;resource的默认是byName,如果找不到指定的name,会用byType.
  6. bean的默认作用域?

    • singleton,这个定义的bean在spring容器中只有一个bean实例
  7. 什么是AOP?AOP术语?(第四章)

    • aop,即面向切面编程,在aop中的基本单元是aspect(切面)。采取横向抽取机制, 将分散在各个方法中的重复代码提取出来,在程序编译运行阶段织入。
    • aop术语:
      • 切面
      • 连接点
      • 切入点
      • 通知
      • 引入
      • 目标对象
      • 代理
      • 织入
  8. java中有哪些常用的动态代理技术?

    • JDK动态代理
      public class JDKDynamicProxy implements InvocationHandler {
          //声明目标类接口对象(真实对象)
          private TestDao testDao;
          //创建代理的方法,建立代理对象和真实对象的代理关系,并返回代理对象
          public Object createProxy(TestDao testDao){
             this.testDao = testDao;
             //类加载器
             ClassLoader cld = JDKDynamicProxy.class.getClassLoader();
             //被代理对象实现的所有接口
             Class[] clazz = testDao.getClass.getInterfaces();
             //使用代理类进行增强,并返回代理后的对象
             return Proxy.newProxyInstance(cld, clazz, this);
          }
          //
          @Override
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
             //创建一个切面
             MyAspect myAspect = new MyAspect();
             //前增强
             myAspect.check();
             myAspect.except();
             //在目标类上调用方法并传参,相当于调用testDao中的方法
             Object obj = method.invoke(testDao, args);
             //后增强
             myAspect.log();
             myAspect.monitor();
             return obj;
          }
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
    • CGLIB动态代理
    public class CglibDynamicProxy implements MethodInterceptor{
       public Object createProxy(Object target){
          //创建一个动态类对象(增强类对象)
          Enhancer enhancer = new Enhancer();
          //确定要增强的类
          enhancer.setSuperclass(target.getClass());
          //确定代理逻辑对象为当前对象,要求当前对象实现MethodInterceptor的方法
          enhancer.setCallback(this);
          //返回创建的代理类对象
          return enhancer.create();
       }
       @Override
       public Object intercept(Object proxy, Method method, Object[] args) {
             //创建一个切面
             MyAspect myAspect = new MyAspect();
             //前增强
             myAspect.check();
             myAspect.except();
             //在目标类上调用方法并传参,相当于调用testDao中的方法
             Object obj = method.invoke(testDao, args);
             //后增强
             myAspect.log();
             myAspect.monitor();
             return obj;
       }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
  9. AspectJ框架的AOP开发方式有几种?

    • 基于xml配置开发
    • 基于注解开发
  10. 什么是编程式事务管理?在Spring中有哪几种编程式事务管理?(第五章)

  • 代码中显示调用beginTransaction、commfit、rollback等于事务处理相关的方法就是编程式事务管理。
  • 有种事务管理
    • 基于底层api的事务管理
      public interface PlatformTransactionManager{
          TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;//定义符合Spring的事务属性的接口
          void commit(TransactionStatus status) throws TransactionException;//事务状态的表示
          void roolback(TransactionStatus status) throws TransactionException;//应用程序开发人员可以选择捕获和处理
      }
      
      1
      2
      3
      4
      5
    • 基于TransactionTemplate的编程式事务管理
    transactionTemplate execute(new TransactionCallback() {
       protected void doInTransactionWithoutResult(TransactionStatus status) {
          try {
             updateOperaction1();
             updateOperaction2();
          } catch(SomeBusinessException ex) {
             status.setRollbackOnly();
            }
       }
    })
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
  1. 简述声明式事务管理的处理方式。

    • xml声明式事务管理

    • @Transactional注解声明式事务管理

  2. Spring Framework中有几个模块?作用是?

    • Spring 核心容器

    • 该层基本上是 Spring Framework 的核心。它包含以下模块:

      • Spring Core
      • Spring Bean
      • SpEL (Spring Expression Language)
      • Spring Context
    • 数据访问/集成 – 该层提供与数据库交互的支持。它包含以下模块:

      • JDBC (Java DataBase Connectivity)
      • ORM (Object Relational Mapping)
      • OXM (Object XML Mappers)第 367 页 共 485 页
      • JMS (Java Messaging Service)
      • Transaction
    • Web

    • 该层提供了创建 Web 应用程序的支持。它包含以下模块:

      • Web
      • Web – Servlet
      • Web – Socket
      • Web – Portlet
    • AOP

    • 该层支持面向切面编程

    • Instrumentation

    • 该层为类检测和类加载器实现提供支持。

    • Test

    • 该层为使用 JUnit 和 TestNG 进行测试提供支持。

    • 几个杂项模块:

    • Messaging

      • 该模块为 STOMP 提供支持。它还支持注解编程模型,该模型用 于从 WebSocket 客户端路由和处理 STOMP 消息。
    • Aspects

      • 该模块为与 AspectJ 的集成提供支持。
  3. spring 中有多少种 IOC 容器?

    • BeanFactory - BeanFactory 就像一个包含 bean 集合的工厂类。它会在客户端 要求时实例化 bean。
    • ApplicationContext - ApplicationContext 接口扩展了 BeanFactory 接口。它 在 BeanFactory 基础上提供了一些额外的功能。
  4. 注解

  • foo
  • @Service用于标注业务层组件
  • @Controller用于标注控制层组件(如struts中的action)
  • @Repository用于标注数据访问组件,即DAO组件
  • @Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
Last Updated: 10/17/2021, 8:21:50 PM