Spring面试题复习(一)

Spring面试题复习(一)

一、Spring是什么?

Spring是一个轻量级的开发框架,常说的Spring框架,就是指Spring Framework,它是很多模块的集合,这些模块可以帮助我们开发人员简化开发,这些模块有核心容器、数据访问/继承、web、AOP、消息和测试模块。主要有以下几个重要的模块:

  • Spring Core:核心类库,Spring框架几乎所有的功能都依赖于此类库,主要提供IOC依赖注入功能。
  • Spring Context:提供框架式的Bean访问方式,以及企业级功能(定时任务等);
  • Spring AOP:提供面向切面编程的服务
  • Spring JDBC:数据库连接
  • Spring Test: 提供了对JUnit单元测试的支持
  • Spring Web:创建web应用程序提供支持

二、SpringIOC容器

IOC:即控制反转,是一种设计思想,就是将原先在代码中创建对象的控制权,交给了IOC容器,由IOC容器帮我们创建;我们在需要的时候,只需要配置好配置文件或者使用注解,就可以将对象创建出来,完全不需要知道对象是如何被创建的。而依赖注入(DI)就是实现控制反转的具体方法,

利用java的反射机制,根据配置文件在运行时动态的创建对象以及管理对象,调用对象的方法。

IOC可以帮助维护对象之间的依赖关系,对象之间的依赖关系交给了IOC容器来管理。

spring实现IOC的三种方式:构造器注入、setter方法注入、根据注解注入。

SpringIOC的初始化过程:首先读取xml配置文件中的信息,然后将读取到的信息解析为BeanDefinition,最后将BeanDefinition注册到BeanFactory中。

三、SpringAOP

AOP:即面向切面编程,将每个业务都需要处理但却与业务逻辑无关的方法抽离出来,例如(日志,事务处理、权限控制等),封装为切面,注入到需要增强的方法上,减少系统 重复代码降低了耦合性,提高了程序的维护性。

Spring AOP是基于动态代理的,如果代理的对象实现了某个接口的话,那么Spring AOP会使用JDK动态代理,对于没有实现某个接口的类,Spring AOP会使用Cglib,Spring AOP会使用Cglib生成一个被代理的子类作为代理。

AOP的基本概念:切面、连接点、切入点、通知、目标对象等

  • 切面(Aspect):在实际应用中,切面通常是指封装的用于横向插入系统功能(如日志、事务)的类,该类被Spring容器识别为切面,需要在配置文件中通过元素指定。
  • 连接点(Joinpoint):在程序执行过程中的某个阶段点,实际上是对象的一个操作,方法的调用或异常的抛出。在SpringAOP中连接点就是指方法的调用。
  • 切入点(PointCut):是指切面与程序流程的交叉点,即那些需要处理的连接点,通常在程序中,切入点指的是类或者方法名,如某个通知要应用到所有以add开头的方法中,那么所有满足这一规则的方法都是切入点。
  • 通知(Advice):AOP框架在特定的切入点执行的增强处理,即在定义好的切入点处所要执行的程序代码,可以理解为切面类中的方法,它是切面的具体实现。
  • 代理(Proxy):将通知应用到目标对象之后,被动态创建的对象。
  • 织入(Weaving):将切面代码插入到目标对象上,从而生成代理对象的过程。
动态代理
JDK动态代理

JDk动态代理通过调用Proxy类的newProxyInstance()方法来创建代理对象。对于使用使用业务接口的类,Spring默认会使用JDK动态代理来实现AOP。

前提是代理的类必须要实现一个接口,否则不能使用JDK代理。

创建代理类实现InvocationHandler()接口,同时创建一个切面类,定义增强方法。

public class ProxyInvoactionHandler implements InvocationHandler {
    UserService userService = new UserServiceImpl();

    MyAspect myAspect = new MyAspect();

    public Object createProxy(UserService userService) {

        return Proxy.newProxyInstance(this.getClass().getClassLoader(), userService.getClass().getInterfaces(), this);

    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        myAspect.before();
        Object invoke = method.invoke(userService, args);
        myAspect.after();
        return invoke;
    }
}

进行测试

public class Test {
    @org.junit.Test
    public void test01() {
        ProxyInvoactionHandler proxy=new ProxyInvoactionHandler();
        UserService userService=new UserServiceImpl();
        UserService userService1 = (UserService) proxy.createProxy(userService);
        userService1.say();

    }
}
CGLIB代理

如果要代理的类没有实现接口的话,就可以使用CGLIB代理,对指定的目标类生成一个子类,并对子类进行增强。

public class CglibProxy implements MethodInterceptor {

    UserService2 userService2 = new UserService2();

    MyAspect myAspect = new MyAspect();

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        myAspect.before();
        Object object = method.invoke(userService2, objects);
        myAspect.after();
        return object;
    }
}

测试

@org.junit.Test
    public void test02() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(UserService2.class);
        enhancer.setCallback(new CglibProxy());
        UserService2 userService2 = (UserService2) enhancer.create();
        userService2.say();
    }
JDK动态代理和CGLIB动态代理的区别:
  1. JDk动态代理本质上是实现了被代理的对象的接口,而CGLIB本质是继承了被代理的对象,覆盖其中的方法。
  2. JDK动态代理只能对实现了接口的类生成代理,CGLIB则没有这个限制,因此CGLIB可以对没有实现接口的类生成代理,但是CGLIB是继承被代理的对象,所以CGLIB不能对final类、private方法和static方法进行代理。
  3. JDK动态代理是JDK自带的,而CGLIB动态代理需要引入第三方jar包,而Spring的核心包中已经继承了CGLIB所使用的包,所以使用Spring进行开发时不需要导入jar包。
  4. JDK动态代理是通过发射极致调用,CGLIB是通过FastClass机制直接调用。
  5. 在性能上,JDK1.7之前,由于使用了FastClass机制,所以CGLIB在执行效率上笔JDK快,但是从JDK1.开始,JDK动态代理已经明显比CGLIB快了。
为什么JDK动态代理执行对实现了接口的类生成代理?

因为JDK动态代理生成的类已经继承了Proxy类,所以无法在使用继承的方式对类实现代理。在运行时newProxyInstance内部会以缓存形式通过字节码生成一个代理类,这个代理类已经继承了Proxy类,同时实现了我们传入的一对接口,由于Java是单继承的,所以JDK动态代理只能代理接口。

四、Spring容器

  • BeanFactory和ApplicationContext的区别?
    • BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当做Spring的容器
      1. BeanFactory是Spring里面最底层的接口,是IOC的核心,定义了IOC的基本功能,包含Bean的定义、加载、实例化、依赖注入、和生命周期的管理。ApplicationContext是BeanFactory的子类,除了提供BeanFactory所具有的的功能外,还提供了更完整的功能:
        • 继承MessageSource,因此支持国际化。
        • 统一的资源文件访问方式。
        • 提供在监听器中注册bean的事件。
        • 同时加载多个配置文件。
        • 载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层。
      2. BeanFactory采用的是延迟加载的形式来注入bean的,只有在使用到某个Bean时(调用getBean()),才对Bean进行加载实例化。这样我们就不能提前发现一些存在的Spring的配置问题。如果Bean的某个属性没哟注入,BeanFactory加载后,直至第一次使用调用getBean方法才会抛出异常。
      3. ApplicationContext是在容器启动时,一次性加载所有的bean,这样在容器启动时,就可以发现Spring中存在配置错误,这样有利于检查所依赖的属性是否注入。ApplicationContext启动后预加载所有的单实例Bean,所以在运行的时候速度非常快,因为他们已经创建好了。相对于BeanFactory,ApplicationContext唯一不足的是占用内存空间,当应用程序配置Bean较多时,程序启动较慢。
    • BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。
    • BeanFactory通常以编程的方式被创建,ApplicationContext还能以声明的方式创建,如使用ContextLoader。
  • BeanFactory

    Spring容器最核心也是最基础的接口,基础IOC容器,本质是个工厂类,用于管理bean工厂,最核心的功能是加载bean,也就是getBean方法,通常不直接使用该接口,而是使用其子接口。

  • ApplicationContext

    高级IOC容器,BeanFactory的子接口,在BeanFactory的基础上进行了扩展。包含BeanFactory的所有功能,还提供了其他高级的特性。正常情况下,我们都是使用ApplicationContext。

  • FactoryBean

    是一个工厂Bean,使用了工厂方法模式,实现该接口的类可以自己定义要创建的Bean实例,只需要实现它的getObject方法即可。

五、了解Bean的生命周期

  1. Bean的实例化阶段:创建一个Bean对象。
  2. Bean的实例的属性填充阶段:为Bean实例的属性赋值
  3. Bean实例的初始化阶段:对Bean实例进行初始化
  4. Bean实例的正常使用阶段
  5. Bean实例的销毁阶段:容器关闭后,将Bean实例销毁。

六、Spring 框架中都用到了哪些设计模式?

  1. 工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例;
  2. 单例模式:Bean默认为单例模式。
  3. 代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;
  4. 模板方法:用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。
  5. 观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现–ApplicationListener。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值