Java面试题一
面试官:spring和springboot区别,redis的数据类型,springboot有哪些注解,bean和value注解说一下,数据库的索引和存储过程,MQ,注解读取springboot配置文件
一.spring和springboot区别:
答: spring:其实你说的spring准确来说是指spring framework。spring Framework是一站式的轻量级的java开发框架,核心是控制反转(IoC)和面向切面(AOP),针对于开发的WEB层(springMVC)、业务层(IoC)、持久层(jdbcTemplate)等都提供了多种配置解决方案。
IOC就是控制权的转移。以前我们对象的依赖都是通过自己创建的,而现在这些都交给了spring容器来管理这些依赖。那么什么是spring容器呢?从宏观的角度来看他就像一个大水桶,而桶里的水就可以把他看作是bean,当然如果从代码角度来看,我们说的就是ApplicationContext。
依赖注入,就是由IoC容器在运行期间,动态地将某种依赖关系注入到对象之中。
Spring对bean的管理(注入对象):
1.xml三种方式:
2.注解实现:
创建对象有四个注解
(1)@Component
(2)@Controller
(3)@Service
(4)@Repository
目前这四个注解功能是一样的,都创建对象
spring属性注入方式:
1.构造注入(带参构造,建议无参也写上)
<bean id="person" class="com.cmy.entity.Person"> <!--constructor-arg:代表构造函数中的一个参数 索引从0开始--> <constructor-arg type="java.lang.String" value="VizualProphet"></constructor-arg> <constructor-arg type="int" value="16"></constructor-arg> </bean>
2.P命名空间注入
注意点:也要有set方法,要在配置文件引入 xmlns:p="http://www.springframework.org/schema/p" aop:xmlns:aop="http://www.springframework.org/schema/aop"
<bean id="person" class="com.cmy.entity.Person" p:name="VizualProphet" p:age="16"> </bean>
3.set注入
4.注解注入
注入复杂类型属性
AOP就是面向切面。面向切面其实就是对方法增强的一种方式。原理就是通过代理模式遵守开闭原则,实现专心做事的功能!!! (就拿我们的业务来说吧,可能我们做很多的模块开发,都需要日志记录,性能统计,安全控制,事务处理,异常处理等东西,但这些都是交叉业务,我们不应该在这些业务上花费太多的时间,我们更应该关心的是主业务的实现!)
AOP增强处理类型
- 前置增强:目标方法调用前
- 后置增强:目标方法调用后
- 环绕增强:前置+后置
- 异常抛出增强:只有在目标方法抛出异常时才执行
- 最终增强:finally
AOP术语
多种方式实现AOP
Ø JDK动态代理是通过接口中的方法名(InvocationHandler的invoke(Object proxy, Method method, Object[] args)方法),在动态生成的代理类中调用业务实现类的同名方法;
Ø CGlib动态代理是通过继承业务类 MethodInterceptor intercept(),不能代理final修饰的类,生成的动态代理类是业务类的子类,通过重写业务方法进行代理;
Ø 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
Ø 如果目标对象实现了接口,可以强制使用CGLIB实现AOP
Ø [aop:config proxy-target-class="true"] 强制切换成CGLIB动态代理
Ø 如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
编程式增强 就是不借助spring自己写增强类。
声明式增强
顾问包装通知 NameMatchMethodPointcutAdvisor/Regx....Advisor
顾问代理生成器
- 自动顾问代理生成器:DefaultAdvisorAutoProxyCreator
- 名称顾问代理生成器:BeanNameAutoProxyCreator
<!---自动顾问代理生成器默认为Spring中所有的Bean对象创建代理 无需使用ID注入--> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"> </bean>
环绕增强
环绕增强相当于前置增强和后置增强的结合体,使用<aop:around>处理
<!--将目标对象声明到Spring容器中--> <bean id="doSomeService" class="com.cmy.service.impl.DoSomeServiceImpl"></bean> <!-- 声明增强方法所在的Bean --> <bean id="advice" class="com.cmy.around.AroundLogger"></bean> <!-- 配置切面 --> <aop:config> <aop:aspect ref="advice"> <aop:around method="aroundLogger" pointcut="execution(* com.cmy.*.*.*(..))"/> </aop:aspect> </aop:config>
异常抛出增强
异常增强处理,在目标方法抛出异常后织入;使用<aop:after-throwing>处理
-*<!--将目标对象声明到Spring容器中--> <bean id="doSomeService" class="com.cmy.service.impl.DoSomeServiceImpl"></bean> <!--将advice声明到容器中--> <bean id="advice" class="com.cmy.exception.errorAdvice"></bean> <!--声明异常抛出增强--> <aop:config> <!-- 定义切入点 --> <aop:pointcut id="pointcut" expression="execution(* com.cmy.service.*.*(..))" /> <!-- 引用包含增强方法的Bean --> <aop:aspect ref="advice"> <!-- 将afterThrowing()方法定义为异常抛出增强并引用pointcut切入点 --> <!-- 通过throwing属性指定为名为e的参数注入异常实例 --> <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="e" /> </aop:aspect> </aop:config>
最终增强 <aop:after> 类似finally
<!--将目标对象声明到Spring容器中--> <bean id="doSomeService" class="com.cmy.service.impl.DoSomeServiceImpl"></bean> <!--将advice声明到容器中--> <bean id="advice" class="com.cmy.after.AfterLogger"></bean> <!--声明异常抛出增强--> <aop:config> <!-- 定义切入点 --> <aop:pointcut id="pointcut" expression="execution(* com.cmy.service.*.*(..))" /> <!-- 引用包含增强方法的Bean --> <aop:aspect ref="advice"> <!-- 将afterThrowing()方法定义为异常抛出增强并引用pointcut切入点 --> <!-- 通过throwing属性指定为名为e的参数注入异常实例 --> <aop:after method="afterLogger" pointcut-ref="pointcut" /> </aop:aspect> </aop:config>
JdbcTemplate+Spring
来源:为了使 JDBC 更加易于使用,Spring 在 JDBCAPI 上定义了一个抽象层, 以此建立一个JDBC存取框架,Spring Boot Spring Data-JPA。
缺点:不支持关联映射和属性注入,所以在SQL方向的操作我们仍需使用MyBatis
JdbcTemplate主要提供以下五类方法:
1、execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句;
Execute、executeQuery、executeUpdate
2、update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语句 SQL SERVCER(GO SQL语句 GO) ;
3、query方法及queryForXXX方法:用于执行查询相关语句;
4、call方法:用于执行存储过程、函数相关语句。
Spring事务
事务:就是作为单个逻辑工作单元执行的一系列操作,要么都执行,要么都不执行,不可分割的逻辑单元。
事务特性:原子性,一致性,隔离性(并发事务之间相互独立、隔离),持久性(对数据库的修改被永久保持)
Spring对事务的整合
在Spring中,所有操作事务的类都继承自 PlatformTransactionManager
事务隔离级别:
- ISOLATION_READ_UNCOMMITTED:读未提交
- ISOLATION_READ_COMMITTED:读已提交
- ISOLATION_REPEATABLE_READ:可重复读
- ISOLATION_SERIALIZABLE:串行化
脏读:A事务读取B事务尚未提交的更改数据,并在这个数据的基础上进行操作,这时候如果事务B回滚,那么A事务读到的数据是不被承认的。
不可重复读:不可重复读是指A事务读取了B事务已经提交的更改数据。假如A在取款事务的过程中,B往该账户转账100,A两次读取的余额发生不一致。
幻读:A事务读取B事务提交的新增数据,会引发幻读问题。幻读一般发生在计算统计数据的事务中,例如银行系统在同一个事务中两次统计存款账户的总金额,在两次统计中,刚好新增了一个存款账户,存入了100,这时候两次统计的总金额不一致。
事务传播行为:
配置事务的方式:
1.代理工厂配置事务 org.springframework.transaction.interceptor.TransactionProxyFactoryBean
<!--配置Spring的事务管理器,默认在发生异常的情况下回滚,否则提交--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!--配置Spring 事务的代理工厂--> <bean id="transactionFactory" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager" ref="transactionManager"/> <property name="target" ref="accountService"/> <property name="transactionAttributes"> <props><!--键值 key为具体的方法名 value可以为传播行为或隔离级别--> <prop key="transferMoney">ISOLATION_READ_COMMITTED</prop> </props> </property> </bean>
2.使用aop方式配置事务
<!--配置Spring的事务管理器,默认在发生异常的情况下回滚,否则提交--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 通知 --> <tx:advice transaction-manager="transactionManager" id="txAdvice"> <tx:attributes> <tx:method name="transferMoney" propagation="REQUIRED" isolation="READ_COMMITTED" /><!-- transferMoney的事务隔离级别和传播行为 --> </tx:attributes> </tx:advice> <!-- 切面 --> <aop:config> <aop:pointcut expression="execution(* com.cmy.service.*.*(..))" id="myCut" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="myCut" /> </aop:config>
3.使用注解方式配置
<!--配置Spring的事务管理器,默认在发生异常的情况下回滚,否则提交--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!--开启事务的注解配置--> <tx:annotation-driven/>
@Transactional(isolation=Isolation.READ_COMMITTED,propagation = Propagation.REQUIRED )
不管如何,以上三种都需要在Application.xml中配置事务管理器
mybatis-spring 1.3.0
重点!!!!!配置application.xml
<!-- 引入属性文件 --> <context:property-placeholder location="database.properties"/> <!--注册DAO层:mapper的代理对象--> <bean id="accountDao" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="mapperInterface" value="com.cmy.dao.AccountDao"></property> <property name="sqlSessionFactory" ref="sqlSessionFactory"></property> </bean> <!--配置service层对象--> <bean id="accountService" class="com.cmy.service.impl.AccountServiceImpl"> <property name="dao" ref="accountDao"></property> </bean> <!-- 配置数据源 spring内置的数据源--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${driver}"></property> <property name="url" value="${url}"></property> <property name="username" value="${user}"></property> <property name="password" value="${password}"></property> </bean> <!-- sqlSessionFactory 创建SqlSession对象的工厂 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <!-- Mybatis的大配置文件 --> <property name="typeAliasesPackage" value="com.cmy.entity"></property> <!-- 扫描sql配置文件:mapper需要的xml文件 --> <property name="mapperLocations" value="com/cmy/dao/*.xml"/> </bean> <!-- MapperScannerConfigurer 扫描mapper文件扫描器 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.cmy.dao"></property> </bean> <!-- transactionManager 事务管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 事务通知--> <tx:advice transaction-manager="transactionManager" id="txAdvice"> <tx:attributes> <!--get系列方法设置事务的隔离级别和传播行为--> <tx:method name="get*" isolation="READ_COMMITTED" propagation="REQUIRED"/> </tx:attributes> </tx:advice>
spring+mybatis整合注解的方式
:只需要开启注解,然后和之前一样 配置上数据源 事务管理器 包扫描器 sqlsession工厂
<!--开启Spring IOC和DI的注解支持--> <context:component-scan base-package="com.cmy"/> <context:annotation-config/> <!--开启注解对声明式事务的注解支持--> <tx:annotation-driven/>
然后使用对应的注解完成实现
spring 配置补充
<!-- 引入属性文件 --> <context:property-placeholder location="database.properties"/> <!---引入多个属性文件-> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="classpath:database.properties"></property> </bean> <!--在spring中配置JNDI数据源--> <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <!--通过jndiName指定引用的JNDI数据源名称 --> <property name="jndiName"> <value>java:comp/env/jdbc/mysql</value> </property> </bean>
SpringBean的作用域
Spring的自动装配
部署模式:Tomcat + WAR包 不能随JAVAEE容器启动而装载,所以出现了boot!
。
springboot:可以看作是sring框架的扩展,没有了之前的大量xml配置,更高效节省时间。application.yml或者.propterties 更方便
spring-boot-starter-web为我们提供了嵌入的Tomcat以及Spring MVC的依赖 springframework.
还提供了第三包 如redis mongdob等 ,再比如test直接包含了springtest,junit,等库!
boot还会它会自动扫描同一个包中的所有类或Main类的子包中的组件
在Spring Boot中默认支持的模板引擎是Thymeleaf(spring-boot-starter-thymeleaf),因为内嵌的web容器不支持以jar的形式运行jsp
部署模式: 使用命令java -jar独立运行jar
总结:pring Boot只是Spring本身的扩展,使开发,测试和部署更加方便
二.springboot有哪些注解?注解读取springboot配置文件?
注解读取springboot配置文件:
@ConfigurationProperties(prefix = "person")
@PropertySource("classpath:person.properties")
springboot的注解:
springboot中除了包含之前的spring和springmvc的注解,他还有多自己的注解!如:
@SpringBootApplication:包含了@ComponentScan、@Configuration和@EnableAutoConfiguration注解。其中
@ComponentScan:让spring Boot扫描到Configuration类并把它加入到程序上下文。
@Configuration :等同于spring的XML配置文件;使用Java代码可以检查类型安全。
@EnableAutoConfiguration :自动配置。
@ComponentScan :组件扫描,可自动发现和装配一些Bean。
@Component:可配合CommandLineRunner使用,在程序启动后执行一些基础任务。
@RestController:注解是@Controller和@ResponseBody的合集,表示这是个控制器bean,并且是将函数的返回值直 接填入HTTP响应体中,是REST风格的控制器。
@Autowired:自动导入。
@PathVariable:获取参数。
@JsonBackReference:解决嵌套外链问题。
@RepositoryRestResourcepublic:配合spring-boot-starter-data-rest使用。
spingboot注解详细总结:https://blog.csdn.net/weixin_40753536/article/details/81285046
mvc和spring注解:https://www.cnblogs.com/caijh/p/7744604.html
3.redis数据类型:
String key-value get set del
List(列表) 可以存储相同字符串 在3.2版本之前,列表是使用ziplist和linkedlist实现的 3.2版本之后,重新引入了一个quicklist的数据结构,列表的底层都是由quicklist实现的,它结合了ziplist和linkedlist的优点
hash 键值对 hash底层的数据结构实现有两种ziplist和hashtable
Set(集合) 存储不同字符串 无序的 intset有序
zset(有序集合) 键值对 key:member(成员) value:score(分值)
redis应用场景: 1.缓存会话(单点登陆)
2.分布式锁(setnx)
3.排行榜或计数器
4.商品列表或用户基础数据列表
5.使用list作为消息队列
6.秒杀。库存扣减
五种类型应用场景:
String:计数器,统计在线人数。存储图片 视频
hash:键值对--用户信息 商品信息等。hash数据的底层ziplist比较节约内存,可以分段存储。如商品图片地址,商品编码固定10位,取前7位作为key,后三位作为field,图片地址作为value,
这样每个hash表都不超过999个,只要把redis.conf中的hash-max-ziplist-entries改为1024,即可。
list:列表类型,可以用于实现消息队列,也可以使用它提供的range命令,做分页查询功能。
set:集合,整数的有序列表可以直接使用set。可以用作某些去重功能,例如用户名不能重复等,另外,还可以对集合进行交集,并集操作,来查找某些元素的共同点
zset:有序集合,可以使用范围查找,排行榜功能或者topN功能。
4.数据库的索引和存储过程
5.mq知道吗?
Message Queue
能干啥?:解耦、异步、削峰
有哪些mq?RocketMQ RabbitMQ ActiveMQ Kafka
其实redis也可以当做一个轻量级的队列服务来使用 入队时不大于10k时,Redis的性能很高。出队,性能更好比rb强多了。
https://blog.csdn.net/u014590757/article/details/79602309
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>