Spring 相关面试题

Spring 相关

1.静态代理和动态代理

代理模式是java常用的设计模式之一,他就是将对一个对象的直接访问变为访问这个对象的代理对象,通过这个代理对象来间接的访问和增强原来的对象。

1.1 为什么要有代理模式呢?

因为开闭原则的体现,一个良好的设计应该对修改关闭,对扩展开放,代理是为了扩展类而存在的。

1.2 静态代理

通过直接编写代理类来实现的代理被称为静态代理。静态代理要求我们在开发阶段就为目标类编写对应的代理类。他的优点是简单易行,执行效率高,但是缺点是是比较死板,工作量大,难以适应灵活多变的需求,如果是需要为多个类进行代理,并且代理类的功能是一致的,那么我们需要为每一个具体类实现一个代理类,就会很麻烦.

1.3 动态代理

动态代理是动态的生成具体委托类的代理类对象。与静态代理不同的是,动态代理不需要为各个委托类逐一实现代理类,而是为一类代理类写一个具体的实现类就行了。

1.4 java常用的两种动态代理的模式

(1)JDK动态代理

JDK自带的创建动态代理的API帮助我们在程序运行时从内存中动态的生成并装载代理类的字节码。jdk的java.lang.reflect.proxy类的newProxyInstance()方法可以为我们动态生成(实现了指定接口的)代理对象。我们需要实现InvocationHandler接口的类实现代理逻辑。

(2)CGLIB动态代理

CGlib动态代理通过(动态字节码技术)为一个目标类创建子类,然后在子类中覆盖父类的方法,加入自己的处理逻辑。

(3)JDK动态代理 VS CGLIB动态代理

CGlib创建的动态代理对象在性能方面要比JDK创建的动态代理对象要高不少,但是创建代理对象花费的时间比JDK动态代理多的多,所以对于一次创建多次使用的对象用GClib更合适,反之,用JDK动态代理

2.IOC和DI

2.1 IOC作用

用来减低计算机代码之间的耦合度。

2.2 IOC-控制反转

是对组件对象控制权的转移。是把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。

2.3 DI

IOC中最常见的方式叫做依赖注入,例如:Class A中用到了Class B的对象b,一般情况下,需要在A的代码中显式的new一个B的对象。采用依赖注入技术之后,A的代码只需要定义一个私有的B对象,不需要直接new来获得这个对象,而是通过相关的容器控制程序来将B对象在外部new出来并注入到A类里的引用中。

根据@Autowaired注解,ioc容器会根据类型或者名称去找到对应的类。

2.4 依赖注入的方式

Spring支持setter注入和构造器注入,通常使用构造器注入来注入必须的依赖关系,对于可选的依赖关系,则setter注入是更好的选择,setter注入需要类提供无参构造器或者无参的静态工厂方法来创建对象。总之,把要注入的抽象接口new出来的对象放在外面传入进来,那就不用依赖具体的实现类。

(1)构造器注入
public class UserService{
	//创建dao接口引用指向实现类对象--直接创建对象
	private UserDao userDao;
	//使用有参构造方法
	public UserService(UserDao userDao){
		this.userDao=userDao;
	}
}
(2)setter注入

同样的,我们也可以使用增加一个setter的方式来传入一个创建好的UserDaoImpl对象

public class UserService{
	//创建dao接口引用指向实现类对象--直接创建对象
	private UserDao userDao;
	public void setUserDao(UserDao userDao){
			this.userDao=userDao;
	}
}
(3)接口注入

接口注入是使用接口来提供setter方法,首先得创建一个接口

public interface InjectDao{
	void injectDaoImpl(UserDao userDao);
}

然后让UserService实现该接口

public class UserService implements InjectDao{
	//创建dao接口引用指向实现类对象--直接创建对象
	private UserDao userDao;
	public void injectDaoImpl(UserDao userDao){
			this.userDao=userDao;
	}

IoC中最基本的Java技术就是“反射”编程。通俗的说,反射就是根据给出的类名(字符串)来生成对象。这种编程方式可以让应用在运行时才动态决定生成哪一种对象。

3.反射

反射可以让我们在运行时获取类的属性,方法,构造方法、父类、接口等信息,通过反射还可以让我们在运行期实例化对象、调用方法、即使方法或属性是私有的的也可以通过反射的形式调用

想在运行时使用类型信息,必须获取对象(比如类Base对象)的Class对象的引用,使用功能Class.forName(“Base”)可以实现该目的,或者使用base.class。注意,有一点很有趣,使用功能”.class”来创建Class对象的引用时,不会自动初始化该Class对象,使用forName()会自动初始化该Class对象。为了使用类而做的准备工作一般有以下3个步骤:

  • 加载:由类加载器完成,找到对应的字节码,创建一个Class对象
  • 链接:验证类中的字节码,为静态域分配空间
  • 初始化:如果该类有超类,则对其初始化,执行静态初始化器和静态初始化

4.AOP

AOP称为面向切面编程,将约定利用动态代理的技术织入到相应的流程中去。

AOP用处

在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子。

AOP的基本概念

将通知织入到切入点指定的连接点处

(1)Aspect(切面):通常是一个类,里面可以定义切入点和通知

(2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用

(3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around

(4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式

(5)AOP代理:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类

Spring AOP

Spring中的AOP代理还是离不开Spring的IOC容器,代理的生成,管理及其依赖关系都是由IOC容器负责,Spring默认使用JDK动态代理,在需要代理类而不是代理接口的时候,Spring会自动切换为使用CGLIB代理,不过现在的项目都是面向接口编程,所以JDK动态代理相对来说用的还是多一些。

通知类型介绍

(1)Before:在目标方法被调用之前做增强处理,@Before只需要指定切入点表达式即可

(2)AfterReturning:在目标方法正常完成后做增强,@AfterReturning除了指定切入点表达式后,还可以指定一个返回值形参名returning,代表目标方法的返回值

(3)AfterThrowing:主要用来处理程序中未处理的异常,@AfterThrowing除了指定切入点表达式后,还可以指定一个throwing的返回值形参名,可以通过该形参名

来访问目标方法中所抛出的异常对象

(4)After:在目标方法完成之后做增强,无论目标方法时候成功完成。@After可以指定一个切入点表达式

(5)Around:环绕通知,在目标方法完成前后做增强处理,环绕通知是最重要的通知类型,像事务,日志等都是环绕通知,注意编程中核心是一个ProceedingJoinPoint

5.bean的生命周期

在这里插入图片描述
解说:

(1)BeanFactoryPostProcessor的postProcessorBeanFactory()方法:若某个IoC容器内添加了实现了BeanFactoryPostProcessor接口的实现类Bean,那么在该容器中实例化任何其他Bean之前可以回调该Bean中的postPrcessorBeanFactory()方法来对Bean的配置元数据进行更改,比如从XML配置文件中获取到的配置信息。

(2)Bean的实例化:Bean的实例化是使用反射实现的。

(3)Bean属性注入:Bean实例化完成后,利用反射技术实现属性及依赖Bean的注入。

(4)BeanNameAware的setBeanName()方法:如果某个Bean实现了BeanNameAware接口,那么Spring将会将Bean实例的ID传递给setBeanName()方法,在Bean类中新增一个beanName字段,并实现setBeanName()方法。

(5)BeanFactoryAware的setBeanFactory()方法:如果某个Bean实现了BeanFactoryAware接口,那么Spring将会将创建Bean的BeanFactory传递给setBeanFactory()方法,在Bean类中新增了一个beanFactory字段用来保存BeanFactory的值,并实现setBeanFactory()方法。

(6)ApplicationContextAware的setApplicationContext()方法:如果某个Bean实现了ApplicationContextAware接口,那么Spring将会将该Bean所在的上下文环境ApplicationContext传递给setApplicationContext()方法,在Bean类中新增一个ApplicationContext字段用来保存ApplicationContext的值,并实现setApplicationContext()方法。

(7)BeanPostProcessor预初始化方法:如果某个IoC容器中增加的实现BeanPostProcessor接口的实现类Bean,那么在该容器中实例化Bean之后,执行初始化之前会调用BeanPostProcessor中的postProcessBeforeInitialization()方法执行预初始化处理。

(8)InitializingBean的afterPropertiesSet()方法:如果Bean实现了InitializingBean接口,那么Bean在实例化完成后将会执行接口中的afterPropertiesSet()方法来进行初始化。

(9)自定义的inti-method指定的方法:如果配置文件中使用init-method属性指定了初始化方法,那么Bean在实例化完成后将会调用该属性指定的初始化方法进行Bean的初始化。

(10)BeanPostProcessor初始化后方法:如果某个IoC容器中增加的实现BeanPostProcessor接口的实现类Bean,那么在该容器中实例化Bean之后并且完成初始化调用后执行该接口中的postProcessorAfterInitialization()方法进行初始化后处理。

(11)使用Bean:此时有关Bean的所有准备工作均已完成,Bean可以被程序使用了,它们将会一直驻留在应用上下文中,直到该上下文环境被销毁。

(12)DisposableBean的destory()方法:如果Bean实现了DisposableBean接口,Spring将会在Bean实例销毁之前调用该接口的destory()方法,来完成一些销毁之前的处理工作。

(13)自定义的destory-method指定的方法:如果在配置文件中使用destory-method指定了销毁方法,那么在Bean实例销毁之前会调用该指定的方法完成一些销毁之前的处理工作。

6.spring的模块

image-20190417151030355

Core包是框架的最基础部分,并提供依赖注入(Dependency Injection)管理Bean容器功能。

Context包,构建于Core包上,提供了一种框架式访问对象的方式,有些像JNDI注册。Context封装包继承了beans包的功能,还增加了国际化(I18N),事件传播,资源装载,以及透明创建上下文,例如通过servlet容器。

DAO包提供了JDBC的抽象层,它可消除冗长的JDBC编码和解析数据库厂商特有的错误代码。并且,JDBC封装包还提供了一种比编程性更好的声明性事务管理方法,不仅仅是实现了特定接口,而且对所有的POJOs都适用。

ORM包为流行的“关系/对象”映射APIs提供了集成层,包括JDO,hibernate和iBatis。通过ORM包,可以混合使用所有Spring提供的特性进行“对象/关系”映射,如前边提到的简单声明性事务管理。

AOP包提供了符合AOP Alliance规范的面向方面的编程实现,例如方法拦截器(method-interceptors)和切点(pointcuts),从逻辑上讲,从而减弱代码的功能耦合,清晰的被分离开。

Web包提供了基本的面向Web的综合特性,例如多方文件上传,利用Servlet listeners进行IoC容器初始化和针对Web的applicationcontext。当与WebWork或Struts一起使用Spring时,这个包使Spring可与其他框架结合。

Web MVC提供了面向Web应用的Model-View-Controller实现。Spring的MVC框架并不是仅仅提供一种传统的实现,它提供了一种清晰的分离模型,在领域模型代码和web form之间。并且,还可以借助Spring框架的其他特性。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值