Spring

作者: 迟凝丶捏米么 | 来源:发表于2019-06-10 22:53 被阅读0次

    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协议的四层模型
    应用层,传输层,网络互联层,主机到网络层


    image.png image.png

    7.如何设计一个数据库


    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冲突解决

    手写图解

    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<String, Object> 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<String, Object> 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

          本文链接:https://www.haomeiwen.com/subject/aerzhftx.html