2019年java中高级java面试题(二)Spring

1、springmvc的运行流程

1. 用户向服务器发送请求,请求被SpringMVC 前端控制器DispatcherServlet捕获;

2. DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;

3. DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter;(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler方法)

4.  提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 在填充Handler的入参过程中,根据你的配置,SpringMVC将帮你做一些额外的工作:

HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息。

数据转换:对请求消息进行数据转换。如String转换成Integer、Double等。

数据根式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等。

数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中。

5.  Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;

6.  根据返回的ModelAndView,选择一个适合的ViewResolver(必须是已经注册到SpringMVC容器中的ViewResolver)返回给DispatcherServlet;

7. ViewResolver 结合Model和View,来渲染视图;

8. 将渲染结果返回给客户端。

2、什么是ioc?

IOC控制反转,不是一种技术,而是一种思想,对象的生命周期不是由程序本身来决定,而是由容器来控制,所以称之为控制反转。

3、IOC和DI的区别? 


 依赖注入和控制反转是对同一件事情的不同描述,从某个方面讲,就是它们描述的角度不同。依赖注入是从应用程序的角度在描述,可以把依赖注入描述完整点:应用程序依赖容器创建并注入它所需要的外部资源;

而控制反转是从容器的角度在描述,描述完整点:容器控制应用程序,由容器反向的向应用程序注入应用程序所需要的外部资源。

4、 什么是aop


aop是面向切面编程,aop是对oop(面向对象编程)的补充和完善,OOP引入封装、继承和多态性等概念建立一种对象的层次结构。当我们需要为不具备上下级关系的对象添加一系列公共的行为时,oop显得很无力。如日志,日志代码所在所有对象之间毫无关系。使用AOP技术,可以将一些系统性相关的编程工作,独立提取出来,独立实现,然后通过切面切入进系统,提高代码的复用性。

1) Aspect :切面,切入系统的一个切面。比如事务管理是一个切面,权限管理也是一个切面;

2) Join point :连接点,也就是可以进行横向切入的位置;

3) Advice :通知,切面在某个连接点执行的操作(分为: Before advice , After returning advice , After throwing advice , After (finally) advice , Around advice );

4) Pointcut :切点,符合切点表达式的连接点,也就是真正被切入的地方;

Spring AOP的五个通知类型

通知类型 作用
before 前置通知
around 环绕通知---需要放行操作
after 后置通知----不论拦截的方法是否有异常
after-returning 后置成功通知---------拦截的方法没油抛出异常就会执行--拦截到的方法必须正确返回;
after-throwing 后置异常通知----拦截的方法如果抛出异常则会执行----有异常执行它没油异常不执行

aop简单使用如下:

定义一个注解

@Target(value = { ElementType.METHOD })
@Retention(value = RetentionPolicy.RUNTIME)
public @interface AnalysisActuator {
	TimeUnit timeType() default TimeUnit.SECONDS;
 
}

定义切面

@Aspect
@Component
public class AnalysisAspect {
	private long stTime;
    //定义切点
	@Pointcut("@annotation(com.whty.aop.annotion.AnalysisActuator)")
	public void declareJoinPointExpression() {
	}
	@Before(value = "declareJoinPointExpression()")
	public void beforemethod() {
		long currentTimeMillis = System.currentTimeMillis();
		stTime=currentTimeMillis;
		System.out.println("开始执行时间"+currentTimeMillis);
	}
	@After(value = "declareJoinPointExpression()")
	public void aftermethod(JoinPoint pjp) {
		//获取方法
		MethodSignature signature = (MethodSignature) pjp.getSignature();
		Method method = signature.getMethod();
		method.getAnnotation(AnalysisActuator.class);
		AnalysisActuator analysisActuator=(AnalysisActuator)method.getAnnotation(AnalysisActuator.class);
		TimeUnit timeType = analysisActuator.timeType();
		long currentTimeMillis = System.currentTimeMillis();
		long t=currentTimeMillis-stTime;
		System.out.println("结束执行的时间为"+currentTimeMillis);
		System.out.println(timeType.convert(t, TimeUnit.MILLISECONDS));
	}
}

 测试

@RestController
public class Demo {
	@RequestMapping(value="/demo")
	@AnalysisActuator(timeType=TimeUnit.MILLISECONDS)
	public Object demo() {
		for (int i = 0; i < 10000000; i++) {
			
		}
		return "hello";
	}
 
}

结果

5、springBean的实例化方式

1)使用类的无参构造函数

<bean id="user" class="com.whty.model.user"></bean>


(2)使用静态工厂创建

public class BeanFactory2{
    public static Bean2 getBean2(){
        return new Bean2();
    }
}
<bean id="bean2" class="com.whty.model.Bean2Factory" factory-method="getBean2"></bean>


(3) 使用实例工厂创建

public class BeanFactory3{
    public static Bean3 getBean3(){
        return new Bean3();
    }
}


 

<bean id="bean3Factory" class="com.whty.model.Bean3Factory" ></bean>
<bean id="bean3" class="com.whty.model.Bean3Factory" factory-method="getBean3"></bean>

6、SpringBean的生命周期

1、spring对bean进行实例化

2、spring将值和bean的引用注入到bean对应的属性中

3、如果bean实现了BeanNameAware接口,spring将bean的id传递给setBeanName()方法

4、如果bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入 

5、如果bean实现了ApplicationContextAware接口,Spring将调用setApplicationContext()方法,将bean所在的应用上下文的
引用传入进来

6、如果bean实现了BeanPostProcessor接口,Spring将调用它们的postProcessBeforeInitialization()方法;

7、如果bean实现了InitializingBean接口,Spring将调用它们的afterPropertiesSet()方法。类似地,如果bean使用init-method声明了初始化方法,该方法也会被调用

在spring初始化bean的时候,如果该bean是实现了InitializingBean接口,并且同时在配置文件中指定了init-method,系统则是先调用afterPropertiesSet方法,然后在调用init-method中指定的方法

8、如果bean实现了BeanPostProcessor接口,Spring将调用它们的post-ProcessAfterInitialization()方法;

9、此时,bean已经准备就绪,可以被应用程序使用了,它们将一直驻留在应用上下文中,直到该应用上下文被销毁;

10、如果bean实现了DisposableBean接口,Spring将调用它的destroy()接口方法。同样,如果bean使用destroy-method声明
了销毁方法,该方法也会被调用

7、 Spring的事物管理


(1)编程式事务管理:将事务管理代码嵌入到业务方法中来控制事务的提交和回滚,在编程式事务中,必须在每个业务操作中包含额外的事务管理代码

编程式事务管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,spring推荐使用TransactionTemplate

(2)声明式事务管理:大多数情况下比编程式事务管理更好用。它将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。事务管理作为一种横切关注点,可以通过AOP方法模块化。Spring通过Spring AOP框架支持声明式事务管理。

声明式事务管理

1.基于xml配置文件实现

2.基于注解实现

8、Spring事物的隔离级别和传播行为


Spring事务的隔离级别:

* read uncommitted  :未提交读.脏读、不可重复读、虚读都是有可能发生.

* read committed    :已提交读.避免脏读.但是不可重复读、虚读是有可能发生.

* repeatable read   :可重复读.避免脏读、不可重复读.但是虚读是有可能发生.

* serializable      :串行化的.避免脏读、不可重复读、虚读的发生.

Spring事务的传播行为

9、 BeanFactory和ApplicationContext有什么区别?

2

BeanFactory:

是Spring里面最低层的接口,提供了最简单的容器的功能,只提供了实例化对象和拿对象的功能;

ApplicationContext:

ApplicationContext 继承了 ListableBeanFactory,这个 Listable 的意思就是,通过这个接口,我们可以获取多个 Bean,最顶层 BeanFactory 接口的方法都是获取单个 Bean 的。

ApplicationContext 继承了 HierarchicalBeanFactory,Hierarchical 单词本身已经能说明问题了,也就是说我们可以在应用中起多个 BeanFactory,然后可以将各个 BeanFactory 设置为父子关系。

ApplicationContext 是Spring的一各更高级的容器,可以通过接口中定义的方法

AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;

获取到AutowireCapableBeanFactory,而AutowireCapableBeanFactory只有一个实现类DefaultListableBeanFactory,

DefaultListableBeanFactory是功能最强大的BeanFactory了。ApplicationContext拥有BeanFactory的功能的同时

还提供了更多的有用的功能;

1) 国际化(MessageSource)

2) 访问资源,如URL和文件(ResourceLoader)

3) 载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层 

4) 消息发送、响应机制(ApplicationEventPublisher)

5) AOP(拦截器

两者装载bean的区别

BeanFactory:

BeanFactory在启动的时候不会去实例化Bean,中有从容器中拿Bean的时候才会去实例化;

ApplicationContext:

ApplicationContext在启动的时候就把所有的Bean全部实例化了。它还可以为Bean配置lazy-init=true来让Bean延迟实例化; 

10、 Spring Bean的作用域之间有什么区别?


Spring容器中的bean可以分为5个范围。所有范围的名称都是自说明的,但是为了避免混淆,还是让我们来解释一下:

(1)singleton:这种bean范围是默认的,这种范围确保不管接受到多少个请求,每个容器中只有一个bean的实例,单例的模式由bean factory自身来维护。

(2)prototype:原形范围与单例范围相反,为每一个bean请求提供一个实例。

(3)request:在请求bean范围内会每一个来自客户端的网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收。

(4)Session:与请求范围类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效。

(5)global-session:global-session和Portlet应用相关。当你的应用部署在Portlet容器中工作时,它包含很多portlet。如果你想要声明让所有的portlet共用全局的存储变量的话,那么这全局变量需要存储在global-session中。

11、 JDK动态代理和Gglib动态代理的区别


1.JDK动态代理是实现了被代理对象的接口,Cglib是继承了被代理对象。

2.JDK和Cglib都是在运行期生成字节码,JDK是直接写Class字节码,Cglib使用ASM框架写Class字节码,Cglib代理实现更复杂,生成代理类比JDK效率低。

3.JDK调用代理方法,是通过反射机制调用,Cglib是通过FastClass机制直接调用方法,Cglib执行效率更高。

12、 BeanFactory与FactoryBean的区别


BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖

FactoryBean它是实现了FactoryBean<T>接口的Bean,通过这个接口能产生指定类型的bean

public class FactoryBeanTest implements FactoryBean<MyBean> {
	@Override
	public MyBean getObject() throws Exception {
		return null;
	}

	@Override
	public Class<?> getObjectType() {
		return null;
	}

	@Override
	public boolean isSingleton() {
		return false;
	}
}

 13、 spring在bean的创建过程中解决循环依赖


Spring先是用构造实例化Bean对象, 创建成功后将对象暴露出来,此时的对象还没有完成属性注入,属于早期对象,此时Spring会将这个实例化结束的对象放到一个Map中,提供set方法设置属性。 

14、 @Transactional使用


@Transactional 注解只能应用到 public 可见度的方法上

默认情况下,spring会对unchecked异常进行事务回滚;如果是checked异常则不回滚。 

RuntimeException(比如空指针,1/0)的异常称为unchecked异常

15、获取spring容器的常用的4种方式


(1)通过Spring提供的ContextLoader

import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
public class SpringContextUtil {
    WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
}


Spring容器初始化时,不能通过下面方法获取Spring 容器 (获取为null)

(2)继承自抽象类ApplicationObjectSupport

说明:抽象类ApplicationObjectSupport提供getApplicationContext()方法。能够方便的获取ApplicationContext。

Spring初始化时。会通过该抽象类的setApplicationContext(ApplicationContext context)方法将ApplicationContext 对象注入。

(3)继承自抽象类WebApplicationObjectSupport

(4) 实现接口ApplicationContextAware

实现该接口的setApplicationContext(ApplicationContext context)方法,并保存ApplicationContext 对象。Spring初始化时,会通过该方法将ApplicationContext对象注入

public class SpringContextUtil implements ApplicationContextAware {
 
    private static ApplicationContext applicationContext;
 
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextUtil.applicationContext = applicationContext;
    }
 
    public static <T> T getBean(Class<T> clazz) {
        return (T) applicationContext.getBean(clazz);
    }
 
}


16、 Spring支持三种依赖注入方式


分别是属性(Setter方法)注入,构造注入和接口注入。 
 

发布了61 篇原创文章 · 获赞 48 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/hzau_itdog/article/details/90735972
今日推荐