spring面试

在这里插入图片描述

DI 就是将类之间的关联交给 spring 容器进行,以前我们一个类要创建一个 connection 连接数据库,会进行 new 操作。有了spring IOC 容器之后,类 A 需要一个连接时,直接向容器说我要一个连接,IOC 容器会自动适当时候创建一个 connection 连接,然后将创建的对象使用各种方法注入到需要连接的类,完成调用

IOC(Inversion of Control):反转控制

由容器主动将需要的资源推送给需要的组件

IOC的实现:

  1. BeanFactory:IOC的基本实现,是spring 内部的基础设施,是面向Spring 本身,不是提供给开发人员使用的
  2. ApplicationContext:BeanFactory 的子接口,提供了更多高级特性。面向Spring 的使用者,几乎所有的场合都使用 ApplicationContext
    • ClassPathXmlApplicationContext:对应类路径下的 XML 格式的配置文件
    • FileSystemXMLApplicationContext:对应文件系统中的 XML 格式的配置文件

实现IOC 步骤

定义用来描述 bean 的配置的 java 类

解析 bean 配置,将 bean 的配置信息转换为上面的 BeanDefinition 对象保存在内存中,spring 中采用 HashMap 进行对象的存储,其中会用到一些 xml 解析技术

遍历存放 BeanDefinition 的 HashMap 对象,逐条取出 BeanDefinition 对象,获取 bean 的配置信息,利用 java的反射机制实例化对象,将实例化后的对象保存在另一个 Map 中3

BeanFactory与ApplicationContext

BeanFactory:比较原始,无法支持 spring 插件,例如AOP、Web应用。

ApplicationContext:是 FactoryBean 的子类,程序员使用中基本替代了 BeanFactory 工作

DI(Dependency Injection):依赖注入

就是在实例化 bean 时将相关联的类实例化并且注入

IOC 就是一种反转控制的思想,而 DI 是对 IOC 的一种具体实现

方式:

  1. 通过 bean 的 setXxx()方法赋值

    <bean id="helloSpring" class="com.tuling.spring.HelloSpring">
    	<property name="hi" ref="hi"/>
    </bean>
    
  2. 通过 bean 的构造器

    1. Spring 自动匹配合适构造器

      <bean id="book" class="com.spring.bean.Book">
           <constructor-arg value= "10010"/>
           <constructor-arg value= "Book01"/>
      </bean >
      
    2. 通过索引指定参数位置

      <bean id="book" class="com.spring.bean.Book">
           <constructor-arg value= "10010" index="0"/>
           <constructor-arg value= "Book01" index="1"/>
      </bean >
      
    3. 通过类型区分重载构造器

      <bean id="book" class="com.spring.bean.Book">
           <constructor-arg value= "10010" index="0" type="java.lang.Integer"/>
           <constructor-arg value= "Book01" index="1" type="java.lang.String"/>
      </bean >
      
  3. p 命名空间

    <bean id="person" class="com.tuling.life.Person" init-method="myInit"
          destroy-method="myDestroy" scope="singleton" p:name="张三" p:address="广州"
          p:phone="1590000000" />
    
  4. 静态工厂方法注入:调用静态方法创建 bean

    //静态工厂 
    //class要写工厂的类;factory-method要写工厂类中用于创建bean的方法;constructor中写静态方法需要的参数
    <bean id="cardStatic" class="com.util.StaticFactory" factory-method="getCar">
        <constructor-arg value="1" />
    </bean>
    
  5. 实例化静态工厂注入

    
    <!-- 实例工厂 -->
    -首先创建一个工厂的bean
    <bean id="cardFactory" class="com.util.InstanceFactory"></bean>
    -factory-bean 指定前面已经创建的 bean; factory-method 指定工厂实例中用于创建 car 的方法; constructor-arg 指定创建 car 方法中传入的参数
    <bean id="cardInstance" factory-bean="cardFactory" factory-method="getCar">
        <constructor-arg value="2" />
    </bean>
    

FactoryBean

已普通 bean 不同,其返回的对象不是指定类的一个实例,其返回的是该工厂 bean 的 getObject 方法所返回的对象。工厂 bean 必须实现 org.springframework.beans.factory.FactoryBean 接口。可以让我们自定义Bean的创建过程

作用:创建比较复杂的 bean

在这里插入图片描述

<bean id="product" class="com.spring.bean.ProductFactory">
	<property name="productName" value="Mp3" />
</bean>

bean 作用域

dao层为什么不能用单例模式:因为单例模式下线程是共享资源的,dao层会创建和销毁连接(连接池会拿到或归还),多个线程会出现冲突

mybatis集成 spring 时,dao层(mapper)可以创建为单例,因为 spring 中使用了 threadLocal 进行安全处理
在这里插入图片描述

Spring生命周期

  1. Spring IOC容器可以管理 bean 的生命周期,Spring 允许在 bean 生命周期内特定的时间点执行指定的任务。

  2. Spring IOC容器对 bean 的生命周期进行管理的过程:

​ ① 通过构造器或工厂方法创建bean实例

​ ② 为bean的属性设置值和对其他bean的引用

​ ③ 调用bean的初始化方法

​ ④ bean可以使用了

​ ⑤ 当容器关闭时,调用bean的销毁方法

  1. 在配置bean时,通过 init-method 和 destroy-method 属性为 bean 指定初始化和销毁方法

  2. bean 的后置处理器

​ ① bean 后置处理器允许在调用初始化方法前后对 bean 进行额外的处理

​ ② bean 后置处理器对IOC容器里的所有 bean 实例逐一处理,而非单一实例。

​ 其典型应用是:检查 bean 属性的正确性或根据特定的标准更改 bean 的属性。

​ ③ bean后 置处理器需要实现接口:

org.springframework.beans.factory.config.BeanPostProcessor。在初始化方法被调用前后,Spring 将把每个 bean 实例分别传递给上述接口的以下两个方法:

  • postProcessBeforeInitialization(Object, String)

  • postProcessAfterInitial ization(Object, String)

  1. 添加bean后置处理器后bean的生命周期

​ ①通过构造器或工厂方法创建 bean 实例

​ ②为 bean 的属性设置值和对其他 bean 的引用

​ ③将bean实例传递给 bean 后置处理器的 postProcessBeforeInitialization() 方法

​ ④调用 bean 的初始化方法

​ ⑤将 bean 实例传递给 bean 后置处理器的 postProcessAfterInitialization()方法

​ ⑥bean可 以使用了

​ ⑦当容器关闭时调用 bean 的销毁方法

自动装配

  • no:不自动装配,可读性高,不易出错

    <bean id="people" class="com.pojo.Peopel">
        <property name="name" value="张三"/>
        <property name="cat" ref="cat"/>
        <property name="dog" ref="dog"/>
    </bean>
    
  • byName:Spring 会根据 class 属性找到实体类,查询所有的 setter 方法,根据 setter 方法后面的名字在配置文件中找到 id 相同的 bean 进行注入

    <bean id="people" class="com.pojo.Peopel" autowire="byName">
        <property name="name" value="张三"/>
    </bean>
    <bean id="cat" class="com.pojo.Cat"/>
    <bean id="dog" class="com.pojo.Dog"/>
    
  • byType:Spring 自动寻找一个与该属性相同的 bean,进行注入(根据 class 进行注入)

    <bean id="cat" class="com.pojo.Cat"/>
    <bean id="dog" class="com.pojo.Dog"/>
    <bean id="people" class="com.pojo.Peopel" autowire="byName">
        <property name="name" value="张三"/>
    </bean>
    
  • constructor:使用构造方法的参数类型进行对象查找,相当于采用 byType 的方式。即 spring 会寻找与参数类型相同的 bean,通过构造函数注入(根据构造函数的参数进行按类型自动装配)

    <bean id="cat" class="com.spring.auto.autowire.Cat"></bean>
    <bean id="dog" class="com.spring.auto.autowire.Dog"></bean>
    <bean id="people" class="com.spring.auto.autowire.Peopel" autowire="constructor">
        <constructor-arg value="2" type="int"></constructor-arg>
    </bean>
    
  • default:默认采用上一级标签的自动装配的取值。

  • 通过注解配置

    • @component 普通组件
    • @Repository 持久化组件
    • @Service 业务逻辑层组件
    • @Controller 表述层控制器
  • 扫描组件

    • <context:component-scan base-package="com.spring.component"/>

    • base-packag 属性指定一个需要扫描的基类包,会扫描这个包及子包

    • 多个包用 , 分隔

    • 如果仅希望扫描包下所有类,可使用 resource-pattren 属性过滤

      <context:component-scan base-package="com.atguigu.component" 
                              resource-pattern="autowire/*.class"/>
      

AOP 面向切面编程

是对传统编程OOP(面向对面编程的补充)

AOP 编程操作对象主要是切面(aspect),而切面用于 模块化横切关注点(公共功能)

  • Aspect 切面:与业务无关,却被业务模块所共同调用的逻辑或者责任封装起来。降低耦合,有利于未来的可维护性。封装横切关注点信息的类,每个关注点体现为一个通知方法

  • 核心关注点:业务处理的主要流程

  • 横切关注点:与业务关系不大的部分。权限认证,日志,事务处理。

  • Advice 增强:切面必须完成的各个具体工作

  • Target 目标:被通知的对象

  • 代理:向目标对象应用通知之后创建的代理对象

  • JointPoint 连接点:程序执行的某个特定位置。横切关注点在程序代码中的具体体现,对应程序执行的某个特定位置,如,某个方法调用前、后、方法捕捉异常后等

  • Pointcut 切点:通过正则或其他方式找到 Advice(增强)应作用于那个连接点 JointPoint

spring支持:默认使用 Java动态代理 来创建AOP 代理,这样就可以为任何接口实例创建代理(实现了接口的类也默认使用 java 动态代理)

当需要代理的类不是代理接口时,spring 会切换为使用CGLIB 代理(没实现接口)

<aop:aspectjautoproxy proxytargetclass=“true” /> 强制使用cglib

aspect 中的 order 属性定义优先级

JAVA动态代理与CGLIB

java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用 InvokerHandler 来处理(InvokerHandler会通过反射接收被代理类的类对象,被代理方法,方法的参数)。JDK 动态代理只能对实现了接口的类生成代理,而不能针对类

CGLIB 动态代理是利用 asm 开源包,对代理对象的 class 文件加载进来,通过修改其字节码生成子类来处理。针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法、类或方法不要声明为final

事务

程序化事务管理:发生错误时,自己写事务回滚

声明式事务管理:使用注解

AspectJ

① @Before:前置通知,在方法执行之前执行

② @After:后置通知,在方法执行之后执行

③ @AfterRunning:返回通知,在方法返回结果之后执行

④ @AfterThrowing:异常通知,在方法抛出异常之后执行

⑥ @Around:环绕通知,围绕着方法执行

@Autowired与@Resource

  • @Autowired:按照类型注入(byType)
@Autowired(required = false)  允许为空
   
@Autowired
@Qualifier("manageServiceImpl")
按照类型注入,当一个类型不是单例(有多个实例)则可以用 Qualifier 进行按 bean 名字选择(byName)
  • @Resource:可以使用属性 name type 指定注入的类型(byName byType)
    • 不指定默认使用 byName

@Required:应用于 bean 属性的 setter 方法,如果尚未填充被注解的属性,容器抛出 BeanInitializationException(注意,spring中要开启注解)

@Autowired:可用在属性,方法,构造函数中。

​ 方法上:创建类时,会自动注入参数,并执行该方法

​ 构造方法:通过构造方法注入

Java变量的初始化顺序为:静态变量或静态语句块–>实例变量或初始化语句块–>构造方法–>@Autowired

​ 属性上:byName注入

@Qualifier:当有多个同类型 bean 时,来根据 ID 选择其中一个

@RequestMapping:将 HTTP 请求映射到处理器中的方法上

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值