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动态代理是通过接口中的方法名(InvocationHandlerinvoke(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中除了包含之前的springspringmvc的注解,他还有多自己的注解!如:

@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>

posted @ 2019-09-03 19:53  VizualProphet_zb  阅读(455)  评论(0编辑  收藏  举报