java3-5年面试题——框架篇

-----Spring------

1.springIOC的理解

spring ioc指的是控制反转,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。交由Spring容器统一进行管理,从而实现松耦合
注入对象:构造方法注入、stter方法注入、接口注入

2.spring是如何通过xml配置或者注解配置生成实例对象的?

简单实列:将对象放入Spring IOC容器中。
1.配置文件方式:  
applictionContext.xml

 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
	<bean id="stu" class="SpringDemo.SpringDemo.Student">
	</bean>
</beans>

main方法:

package SpringDemo.SpringDemo;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App 
{
    public static void main( String[] args )
    {
    	//加载前期解析xml,通过反射的方式创建出来,将对象放入Spring的IOC容器中
    	ApplicationContext context = new ClassPathXmlApplicationContext("applictionContext.xml");
    	//可以通过ApplicationContext的实例对象获取容器中已经存在的对象
    	Student student = (Student) context.getBean("stu");
    	System.err.println(student);
    }
}

2.用@bean注解
package SpringDemo.SpringDemo;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
@Configuration // 声明此类是一个配置类
public class Config {
	@Bean
	public Grade createGrade() {
		return new Grade();
	}
}

3.springIOC的java底层原理

ioc底层原理使用技术 (1)xml配置文件 (2)dom4j解决xml (3)工厂设计模式 (4)反射
java3-5年面试题——框架篇_第1张图片

4.springAOP的理解

AOP,一般称为面向切面编程,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),切面将那些与业务无关,却被业务模块共同调用的逻辑提取、并封装起来,减少了系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证、日志、事务处理等。
AOP思想实现的关键在于AOP代理技术,AOP代理主要分为静态代理动态代理
静态代理的代表为AspectJ;动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。
jdk代理 :JDK动态代理要求该业务Bean必须要有实现的接口,通过和该业务Bean–即目标对象,实现相同的接口保证功能一致。

cglib代理 : CGLib动态代理是通过继承该业务Bean–即目标对象,来保证功能一致,即,生成目标对象的子类, 这个子类对象就是代理对象。

5.springAOP的底层的实现原理

1.JDKProxy动态代理类创建

package com.xia.jdk;

import com.xia.basic.User;
import com.xia.proxy.UserService;
import com.xia.proxy.UserServiceImpl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TestJDKProxy {
    public static void main(String[] args) {
        // 1.创建原始对象
        UserService userService = new UserServiceImpl();
        // 2.创建动态代理

        // InvocationHandler 实现额外功能
        // 用于添加额外功能和之前的MethodInterceptor类似
        // 其实就是对Invocation实现了封装
        InvocationHandler handler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // proxy 原始对象 method原始方法 args 方法参数
                System.out.println("------JDKProxyBefore-----");
                Object ret = method.invoke(userService,args);
                System.out.println("------JDKProxyAfter-----");
                return ret;
            }
        };
        UserService userServiceProxy = (UserService) Proxy.newProxyInstance(
                /*
                * 类加载器功能
                * 1.把对应类的字节码文件加载入jvm内存中
                * 2.创建这个类的类对象 Class
                * 3.借一个类加载器
                * */
                TestJDKProxy.class.getClassLoader(),
                // 获得原始对象的所有的接口 这样就可以创建和原始类实现相同接口的代理类
                userService.getClass().getInterfaces(),
                // 额外功能
                handler);
        userServiceProxy.login(new User());

    }
    
}

2.Cglib动态代理

public class TestCjLib {
    public static void main(String[] args) {
        // 创建原始对象
        UserService userService = new UserService();
        // cglib创建代理对象
        Enhancer enhancer = new Enhancer();
        enhancer.setClassLoader(TestCjLib.class.getClassLoader());
        enhancer.setSuperclass(UserService.class);
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("cglib--before");
                Object ret = method.invoke(userService, "夏冬","123456");
                System.out.println("cglib--after");
                return ret;
            }
        });
        UserService userServiceProxy = (UserService)enhancer.create();
        userServiceProxy.login("xiadong","123456");
    }
}

总结:
jdk动态代理:通过接口创建代理类
cjlib动态代理:通过父类创建代理类

6.AOP的应用场景

前面我们提到AOP主要应用一些非核心业务逻辑中,我们看看AOP常见的应用场景

监控
日志
缓存
鉴权
事务
异常处理
持久化
SpringMVC视图解析器解析流程:

7.spring如何解析视图

1、将SpringMVC控制器中的返回结果封装成一个ModelAndView对象。
2、通过SpringMVC中的视图解析器,使用ViewResolver对控制器返回的ModelAndView对象进行解析,将逻辑视图转换成物理视图。
3、调用View中的render()方法对物理视图进行渲染。

8.spring的常用注解

1、@SpringBootApplication

替代 @SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan

2、@ImportAutoConfiguration

导入配置类,一般做测试的时候使用,正常优先使用@EnableAutoConfiguration

3、@SpringBootConfiguration

替代@Configuration

4、@ImportResource

将资源导入容器

5、@PropertySource

导入properties文件

6、PropertySources

@PropertySource 的集合

7、@Role

bean角色定义为ROLE_APPLICATION(默认值)、ROLE_SUPPORT(辅助角色)、ROLE_INFRASTRUCTURE(后台角色,用户无感)
8、@Scope

指定bean的作用域,默认singleton,其它包括prototype、request、session、globalSession

9、@Lazy

使bean懒加载,取消bean预初始化。

10、@Primary

自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否者将抛出异常。

11、@Profile

指定Bean在哪个环境下被激活

12、@DependsOn

依赖的bean注册完成,才注册当前类,依赖bean不存在会报错。用于控制bean加载顺序

13、@PostConstruct

bean的属性都注入完毕后,执行注解标注的方式进行初始化工作

14、@Autowired

默认按类型装配,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。

9.如何控制事务

有两种事务控制的方法:编程式(硬编码,代码,API)vs 声明式(xml或注解)

声明式的好处:事务管理不侵入开发的组件,更改只需要在定义文件中出现配置即可。业务逻辑对象不会意识到处在事务管理之中,事实上也该如此,因为事务管理是属于系统层面的服务,而不是业务逻辑的一部分。而且不需要事务管理时可关闭,符合开闭原则。(解耦)

Spring声明式事务控制底层就是aop。
例:@Transactional(rollbackFor = Exception.class)

10.Spring BeanFactory与FactoryBean的区别

首先,Spring 里面的核心功能是IOC容器,所谓IOC容器呢,本质上就是一个Bean的容器或者是一个Bean的工厂。

它能够根据xml里面声明的Bean配置进行bean的加载和初始化,然后BeanFactory来生产我们需要的各种各样的Bean。

所以我对BeanFactory的理解了有两个。

BeanFactory是所有Spring Bean容器的顶级接口,它为Spring的容器定义了一套规范,并提供像getBean这样的方法从容器中获取指定的Bean实例。
BeanFactory在产生Bean的同时,还提供了解决Bean之间的依赖注入的能力,也就是所谓的DI。

FactoryBean是一个工厂Bean,它是一个接口,主要的功能是动态生成某一个类型的Bean的实例,也就是说,我们可以自定义一个Bean并且加载到IOC容器里面。

它里面有一个重要的方法叫getObject(),这个方法里面就是用来实现动态构建Bean的过程。

Spring Cloud里面的OpenFeign组件,客户端的代理类,就是使用了FactoryBean来实现的。

11.springboot与springmvc最大的优势在哪?

SpringMVC的优点:
(1)使用简单,学习成本低。
(2)很容易就可以写出性能优秀的程序.
(3)灵活性强,Spring MVC的框架易扩展

SpringMVC的缺点:
(1)Spring与MVC 的Servlet API 耦合,难以脱离容器独立运行
(2)太过于细分,开发效率低
(3)过度追求完美,有过度设计的危险
解决的问题领域是:网站应用程序或者服务开发——URL路由、Session、模板引擎、静态Web资源等等。

SpringBoot的优点:
1、创建独立Spring应用
2、内嵌web服务器
3、自动starter依赖,简化构建配置
4、自动配置Spring以及第三方功能
5、提供生产级别的监控、健康检查以及外部优化配置
6、无代码生成、无需编写XML

SpringBoot的缺点:
1、迭代快
2、封装太深,内部原理复杂,不容易精通

12.一个加了事务注解的“新增方法”,抛出异常,数据有没有添加成功?

转:https://blog.csdn.net/y2020520/article/details/124951764

-----mybatis-----

1.mybatis的结构?

主要分为三层:基础支持层、核心处理层、接口层

基础支持层:数据源模块、事物管理器模块、缓存模块、Binding模块、反射模块、类型转换、日志模块、资源加载、解析器模块
核心处理层:配置解析、参数映射、SQL解析、SQL执行、结果映射、插件
接口层:SqlSession

2.mybatis配置文件如何配置?

MyBatis配置文件分为两类,一类是总配置文件,还有一类是写SQL语句的mapper文件。二者都是XML文件。

主配置文件:提供MyBatis的全局设置, 比方说 日志,数据源,mapper文件的位置等;主配置文件的所有配置信息都是在标签里面的

mapper文件: 主要就是写SQL语句的, 一般就是 一个表对应一个mapper文件。

3.mybatis处理多个参数的几种方式?

1.@Param注解传参法(推荐)
2.Map传参法(推荐)
3.Java Bean传参法(推荐)
4.顺序传参法(不推荐)

4.mybatis占位符有几种?区别是什么?

一、占位符一:#{xxx}
  PreparedStatement 预编译sql语句有?占位符。 xxx表达式的写法。
  参数类型为javabean类, xxx表达式必须和javabean中属性对应的get方法名字一样。
   如果 parameterType 传输单个简单类型值,#{} 括号中可以是 value 或其它名称。
二、占位符二: ¥{xxx}
  Statement拼接 sql语句没有? 占位符会有SQL注入的漏洞。xxx 表达式的写法。
  参数类型为javabean类, xxx 表达式必须和javabean中属性对应的get方法名字一样,
  如果parameterType传输单个简单类型值,{} 括号中只能是 value。

三、区别:

1.#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by “111”, 如果传入的值是id,则解析成的sql为order by “id”.

2.$将传入的数据直接显示生成在sql中。如:order by u s e r i d user_id userid,如果传入的值是111,那么解析成sql时的值为order by user_id, 如果传入的值是id,则解析成的sql为order by id.

3.#方式能够很大程度防止sql注入。$方式无法防止Sql注入。

4.$方式一般用于传入数据库对象,例如传入表名.

5.一般能用#的就别用$.

5.mybatis一级缓存和二级缓存的区别?

一级缓存:SqlSession级别的缓存,缓存的数据只在SqlSession内有效。

二级缓存:mapper级别的缓存,同一个namespace公用这一个缓存,所以对SqlSession是共享的,二级缓存需要我们手动开启

6.Mybatis的类型转换器?

mybatis类型转换器,就是Java类型与数据库的类型之间转换的一个中介,由这个转换器可以对类型进行映射,mybatis对于基础类型都有默认类型转换器,你可以自定义类型转换器替代默认的转换器,大多数情况下你无需替代它,但是对于Java中的复杂类型,比如对象想要映射成数据库的json字符串,那么你就可以自定义类型转换器。
mybatis自定义类型转换器可以继承TypeHandler或BaseTypeHandler两个接口,并实现其中的方法。
BaseTypeHandler继承TypeHandler,它们之间的关系使用了设计模式模板方法。

7.mybatis接口没有实现类,他是如何操作数据库的?

mybatis注解方式通过没有实现类的dao接口进行数据库操作的原理,一句话概括,就是jdk proxy,就是jdk代理

1)原理上:JDK动态动态代理的原理是根据 InvocationHandler 中的invoke()方法,由jdk为你的接口手动生成了一个实现了对应接口的类,因此,你的接口可以调用,这是理解mybatis接口没有实现类能被调用的关键。

2)功能上:可以看出mybatis中的接口就是XML文件的描述,一方面这样做的目的是和spring集成,将接口交给spring管理;另一方面是为了更加方便的管理XML文件(使用接口的package+interface作为namespace,method作为ID。

8.mybatis 与hibernate的对比

mybatis 与hibernate的对比:

Mybatis Hibernate
开发效率 较容易上手;需要手动管理sql 较难上手;无需管理sql,专注业务
入门 简单 入门 较难
sql更加灵活 几乎不用写sql,封装性较大
性能 相对较高 性能相对较低
优化 更容易 优化 较难
适用场合 1.有复杂的查询业务;2.无hibernate实践经验的 1.无复杂的查询业务;2.能够熟练应用hibernate的

你可能感兴趣的:(java,spring)