Spring

1.Spring事务的传播特性

2.Spring事务管理(详解+实例)

3.mem dump中unreachable objects分析

4.tcp滑动窗口作用

  • 保证tcp的可靠性
  • 保证tcp的流控特性
    AdvertisedWindow接收方能接受的大小,EffectiveWindow发送方还能发送数据的大小

5.请求/响应的步骤

  • 客户端连接到web服务器
  • 发送Http请求
  • 服务器接受请求并返回http响应
  • 释放tcp连接(closed:服务器主动关闭,keep-alive:连接会保留一段时间)
  • 客户端浏览器解析html内容

6.tcp/ip协议的四层模型
应用层,传输层,网络互联层,主机到网络层


Spring_第1张图片
image.png
Spring_第2张图片
image.png

7.如何设计一个数据库


Spring_第3张图片
image.png

8.innodb和myisam区别

myisam 默认表级锁,不支持行级锁

读锁为:共享锁,查询为读锁
写锁为:排他锁,增删改为写锁

相关命令:
手动加读锁:lock tables 表名 read
手动释放锁:unlock tables
对select上排他锁:select * from person_info_myisam for update

innodb 默认行级锁,支持表级锁,支持事务

  • 在查询数据时,若sql不含索引,使用表级锁,否则,使用行级锁,或者get锁(普通非唯一索引)
  • 表级的意向锁,分为:IS(共享读锁),IX(排他写锁)

读锁为:共享锁,查询为读锁
写锁为:排他锁,增删改为写锁

相关命令:
查看事务是否自动提交:show variables like 'autocommit'
关闭自动提交:set autocommit = 0
对select上读锁:select * from person_info_myisam lock in share mode

9.事务隔离级别
命令:
查看当前事务级别:select @@tx_isolation
设置当前session的事务隔离级别(未提交读 脏读):set session transaction isolation level read uncommitted

10.对主键索引或者唯一索引会用Gap锁吗
1.如果where条件全部命中,则不会用Gap锁,只会加记录锁
2.如果where条件部分命中或者全不命中,则会加Gap锁
3.Gap锁会用在非唯一索引或者不走索引的当前读中

11.classloader的种类

  • BootStrapClassLoader :c++编写,加载核心库java.*
  • ExtClassLoader:java编写,加载扩展库javax.*
  • AppClassLoader:java编写,加载程序所在目录
  • 自定义ClassLoader:Java编写,定制化加载

12.解决哈希(HASH)冲突的主要方法
数据结构与算法:hash冲突解决

Spring_第4张图片
手写图解

13.elasticsearch原理

反向索引又叫倒排索引,是根据文章内容中的关键字建立索引

建立倒排索引,基于 Lucene 库进行封装,将对搜索引擎的操作都封装成restful的api,同时还考虑了海量数据,实现了分布式,是一个可以存储海量数据的分布式搜索引擎。

14.spring 自动装配发展

  • 模式注解,@component,@since 2.5
  • @Enable模块实现,@EnableServer 参考 @EnableCaching实现,@since 3.1
//1.定义接口
public interface Server {
    /**
     * 启动服务器
     */
    void start();

    /**
     * 关闭服务器
     */
    void stop();

    /**
     * 服务器类型
     */
    enum Type {

        HTTP, // HTTP 服务器
        FTP   // FTP  服务器
    }
}

2.实现上述定义的server接口
@Component // 根据 ImportSelector 的契约,请确保是实现为 Spring 组件
public class FtpServer implements Server {

    @Override
    public void start() {
        System.out.println("FTP 服务器启动中...");
    }

    @Override
    public void stop() {
        System.out.println("FTP 服务器关闭中...");
    }
}

3.实现上述定义的server接口
@Component // 根据 ImportSelector 的契约,请确保是实现为 Spring 组件
public class HttpServer implements Server {

    @Override
    public void start() {
        System.out.println("HTTP 服务器启动中...");
    }

    @Override
    public void stop() {
        System.out.println("HTTP 服务器关闭中...");
    }
}

4.自定义Enable注解,666
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//@Import(ServerImportSelector.class) // 导入 ServerImportSelector
@Import(ServerImportBeanDefinitionRegistrar.class) // 替换 ServerImportSelector
public @interface EnableServer {

    /**
     * 设置服务器类型
     * @return non-null
     */
    Server.Type type();
}

5.类似enablecache的importselector接口实现
public class ServerImportSelector implements ImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        // 读取 EnableServer 中的所有的属性方法,本例中仅有 type() 属性方法
        // 其中 key 为 属性方法的名称,value 为属性方法返回对象
        Map annotationAttributes = importingClassMetadata.getAnnotationAttributes(EnableServer.class.getName());
        // 获取名为"type" 的属相方法,并且强制转化成 Server.Type 类型
        Server.Type type = (Server.Type) annotationAttributes.get("type");
        // 导入的类名称数组
        String[] importClassNames = new String[0];
        switch (type) {
            case HTTP: // 当设置 HTTP 服务器类型时,返回 HttpServer 组件
                importClassNames = new String[]{HttpServer.class.getName()};
                break;
            case FTP: //  当设置 FTP  服务器类型时,返回 FtpServer  组件
                importClassNames = new String[]{FtpServer.class.getName()};
                break;
        }
        return importClassNames;
    }
}

6.注册到 BeanDefinitionRegistry,这里解释一下,如果server接口的实现类(httpserver,ftpserver)没有被定义成bean(例如:没有Component 注解),就需要进行bean的注册
public class ServerImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        // 复用 {@link ServerImportSelector} 实现,避免重复劳动
        ImportSelector importSelector = new ServerImportSelector();
        // 筛选 Class 名称集合
        String[] selectedClassNames = importSelector.selectImports(importingClassMetadata);
        // 创建 Bean 定义
        Stream.of(selectedClassNames)
                .map(BeanDefinitionBuilder::genericBeanDefinition) // 转化为 BeanDefinitionBuilder 对象
                .map(BeanDefinitionBuilder::getBeanDefinition)     // 转化为 BeanDefinition
                .forEach(beanDefinition ->
                        // 注册 BeanDefinition 到 BeanDefinitionRegistry
                        BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry)
                );
    }
}

7.引导类进行测试
@Configuration
@EnableServer(type = Server.Type.HTTP) // 设置 HTTP 服务器
public class EnableServerBootstrap {

    public static void main(String[] args) {
        // 构建 Annotation 配置驱动 Spring 上下文
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        // 注册 当前引导类(被 @Configuration 标注) 到 Spring 上下文
        context.register(EnableServerBootstrap.class);
        // 启动上下文
        context.refresh();
        // 获取 Server Bean 对象,实际为 HttpServer
        Server server = context.getBean(Server.class);
        // 启动服务器
        server.start();
        // 关闭服务器
        server.stop();
        // 关闭上下文
        context.close();
    }
}

  • 条件装配 @condition @since 4.0
//步骤一:自定义注解
@Target({ElementType.METHOD}) // 只能标注在方法上面
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnSystemPropertyCondition.class)
public @interface ConditionalOnSystemProperty {
    /**
     * @return System 属性名称
     */
    String name();

    /**
     * @return System 属性值
     */
    String value();
}

//步骤二:添加conditional判断
public class OnSystemPropertyCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // 获取 ConditionalOnSystemProperty 所有的属性方法值
        MultiValueMap attributes = metadata.getAllAnnotationAttributes(ConditionalOnSystemProperty.class.getName());
        // 获取 ConditionalOnSystemProperty#name() 方法值(单值)
        String propertyName = (String) attributes.getFirst("name");
        // 获取 ConditionalOnSystemProperty#value() 方法值(单值)
        String propertyValue = (String) attributes.getFirst("value");
        // 获取 系统属性值
        String systemPropertyValue = System.getProperty(propertyName);
        // 比较 系统属性值 与 ConditionalOnSystemProperty#value() 方法值 是否相等
        if (Objects.equals(systemPropertyValue, propertyValue)) {
            System.out.printf("系统属性[名称 : %s] 找到匹配值 : %s\n",propertyName,propertyValue);
            return true;
        }
        return false;
    }
}

//步骤三:配置 @Configuration 类
@Configuration
public class ConditionalMessageConfiguration {

    @ConditionalOnSystemProperty(name = "language", value = "Chinese")
    @Bean("message") // Bean 名称 "message" 的中文消息
    public String chineseMessage() {
        return "你好,世界";
    }

    @ConditionalOnSystemProperty(name = "language", value = "English")
    @Bean("message") // Bean 名称 "message" 的英文消息
    public String englishMessage() {
        return "Hello,World";
    }
}

public class ConditionalOnSystemPropertyBootstrap {

    public static void main(String[] args) {
        // 设置 System Property  language = Chinese
        System.setProperty("language", "Chinese");
        // 构建 Annotation 配置驱动 Spring 上下文
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        // 注册 配置Bean ConditionalMessageConfiguration 到 Spring 上下文
        context.register(ConditionalMessageConfiguration.class);
        // 启动上下文
        context.refresh();
        // 获取名称为 "message" Bean 对象
        String message = context.getBean("message", String.class);
        // 输出 message 内容
        System.out.printf("\"message\" Bean 对象 : %s\n", message);
        
        context.close();
    }
}
  • 自动装配

底层装配技术

  • spring模式注解装配
  • spring@Enable模块装配
  • spring条件装配
  • spring工厂加载机制
    - 实现类:SpringFactoriesLoader
    - 配置资源:META-INT/spring.factories

实现方式:
1.激活自动装配@EnableAutoConfiguration
2.实现自动装配xxxAutoConfiguration
3.配置自动装配实现META-INT/spring.factories

15.索引失效场景
例如:一张USER表 有字段属性 name,age 其中name为索引

下面列举几个索引失效的情况

    1. select * from USER where name=‘xzz’ or age=16;

例如这种情况:当语句中带有or的时候 即使有索引也会失效。

  • 2.select * from USER where name like‘%xzz’ ;

例如这种情况:当语句索引 like 带%的时候索引失效(注意:如果上句为 like‘xzz’此时索引是生效的)

  • 3.select * from USER where name=123;(此处只是简单做个例子,实际场景中一般name不会为数字的)
    例如这种情况:如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引
  • 4.如果mysql估计使用全表扫描要比使用索引快,则不使用索引(这个不知道咋举例子了 )
  • 5.假如上述将name和age设置为联合索引,一定要注意顺序,mysql联合所以有最左原则,下面以name,age的顺序讲下

(1)select * from USER where name=‘xzz’ and age =11;

(2)select * from USER where age=11 and name=‘xzz’;

例如上诉两种情况:以name,age顺序为联合索引,(1)索引是生效的,(2)索引是失效的

总结起来就5点吧:
1.索引不存储null值
2.不适合键值较少的列(重复数据较多的列)
3.前导模糊查询不能利用索引(like '%XX'或者like '%XX%')
4.索引失效的几种情况
5.MySQL主要提供2种方式的索引:B-Tree索引,Hash索引
查看文章 MySQL索引失效的几种情况

你可能感兴趣的:(Spring)