手写Spring6(实现应用上下文)

news2025/1/16 15:05:58

文章目录

  • 目标
  • 设计流程
  • 项目结构
  • 一、实现
    • 1、定义实例化前-BeanFactoryPostProcessor
    • 2、定义初始化前后-BeanPostProcessor
    • 3、定义上下文接口--ApplicationContext
    • 4、应用上下文抽象类实现--AbstractBeanFactory
    • 5、获取Bean工厂和加载资源--AbstractRefreshableApplicationContext
    • 6、上下文中对xml配置信息的加载--AbstractXmlApplicationContext
    • 7、应用上下文实现类--ClassPathXmlApplicationContext
    • 8、在Bean创建时完成前置和后置处理
  • 二、测试
    • 1、事先准备
    • 2、 实现 BeanPostProcessor 和 BeanFactoryPostProcessor
    • 3、配置文件
    • 4、不用应用上下文
    • 5、使用应用上下文


目标

上篇文章的代码,原本是需要手动创建bean工厂,并且手动调用xml的资源加载、注册beanDefintion等操作

本章目标是 实现应用上下文,自动创建bean工厂、xml资源加载、实例化前扩展机制、初始化前后置扩展机制等(这也是spring对外提供的上下文api)
在这里插入图片描述


设计流程

创建上下文时
1、创建了bean工厂、资源加载xml、户厕bean定义
2、实现实例化前扩展点BeanFactoryPostProcessor,如果有实现该接口,则调用自定义的逻辑处理
3、注册BeanPostProcessor
4、遍历bean定义,创建bean,且在属性填充后,执行初始化前、初始化、初始化后的扩展逻辑处理

在这里插入图片描述


项目结构

在这里插入图片描述

Spring 应用上下文和对Bean对象扩展机制的类关系,如图


一、实现

1、定义实例化前-BeanFactoryPostProcessor

public interface BeanFactoryPostProcessor {

    /**
     * 在所有的 BeanDefinition 加载完成后,实例化 Bean 对象之前,提供修改 BeanDefinition 属性的机制
     *
     * @param beanFactory
     * @throws BeansException
     */
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

这个接口是满足于在所有的 BeanDefinition 加载完成后,实例化 Bean 对象之前,提供修改 BeanDefinition 属性的扩展机制


2、定义初始化前后-BeanPostProcessor

public interface BeanPostProcessor {


    /**
     * 在 Bean 对象执行初始化方法之前,执行此方法
     *
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

    /**
     * 在 Bean 对象执行初始化方法之后,执行此方法
     *
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

1、这个接口提供了 Bean 对象的扩展点。

2、提供了两个方法:postProcessBeforeInitialization 用于在 Bean 对象执行初始化方法之前,执行此方法、postProcessAfterInitialization用于在 Bean 对象执行初始化方法之后,执行此方法。


3、定义上下文接口–ApplicationContext

public interface ApplicationContext extends ListableBeanFactory {
}
 

1、context 是本次实现应用上下文功能新增的服务包

2、ApplicationContext,继承于 ListableBeanFactory,也就继承了关于 BeanFactory 方法,比如一些 getBean 的方法。

3、ApplicationContext 本身是 Central(中央)接口,但目前还不需要添加一些获取ID和父类上下文,所以暂时没有接口方法的定义

ConfigurableApplicationContext

public interface ConfigurableApplicationContext extends ApplicationContext {

    /**
     * 刷新容器
     *
     * @throws BeansException
     */
    void refresh() throws BeansException;

}

1、ConfigurableApplicationContext 继承自 ApplicationContext,并提供了 refresh 这个核心方法

如果你有看过一些 Spring 源码,那么一定会看到这个方法。 接下来也是需要在上下文的实现中完成刷新容器的操作过程。


4、应用上下文抽象类实现–AbstractBeanFactory

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {

	/**
     * @desc: 刷新容器
     **/
    @Override
    @Override
    public void refresh() throws BeansException {
        // 1、创建BeanFactory,并加载BeanDefintion
        refreshBeanFactory();

        // 2、获取beanFactory
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();

        // 3、在 Bean 实例化之前,执行 BeanFactoryPostProcesso
        invokeBeanFactoryPostProcessors(beanFactory);

        // 4、BeanPostProcessor 需要提前于其他 Bean 对象实例化之前执行注册操作
        registerBeanPostProcessors(beanFactory);

        // 5. 提前实例化单例Bean对象
        beanFactory.preInstantiateSingletons();
    }

    /**
     * @desc: 实例化bean工厂&获取、加载资源&注册Bean定义
     **/
    protected abstract void refreshBeanFactory() throws BeansException;

    protected abstract ConfigurableListableBeanFactory getBeanFactory();

    /**
     * @desc: bean定义加载后,bean实例化前(对bean定义的扩展)
     **/
    private void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        Map<String, BeanFactoryPostProcessor> beanFactoryPostProcessorMap = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
        for (BeanFactoryPostProcessor beanFactoryPostProcessor : beanFactoryPostProcessorMap.values()) {
            beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
        }
    }

    /**
     * @desc: 注册,初始化bean扩展点 
     **/
    private void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        Map<String, BeanPostProcessor> beanPostProcessorMap = beanFactory.getBeansOfType(BeanPostProcessor.class);
        for (BeanPostProcessor beanPostProcessor : beanPostProcessorMap.values()) {
            beanFactory.addBeanPostProcessor(beanPostProcessor);
        }
    }

    /**
     * @desc: 根据类型获取相同类型的map集合
     **/
    @Override
    public <T> Map<String, T> getBeansOfType(Class<T> type) throws org.springframework.beans.BeansException {
        return getBeanFactory().getBeansOfType(type);
    }

    @Override
    public String[] getBeanDefinitionNames() {
        return getBeanFactory().getBeanDefinitionNames();
    }

    @Override
    public Object getBean(String name) throws BeansException {
        return getBeanFactory().getBean(name);
    }

    @Override
    public Object getBean(String name, Object... args) throws BeansException {
        return getBeanFactory().getBean(name, args);
    }

    @Override
    public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
        return getBeanFactory().getBean(name, requiredType);
    }

}

1、AbstractApplicationContext 继承 DefaultResourceLoader 是为了处理 spring.xml 配置资源的加载

2、 实现ConfigurableApplicationContextrefresh()(刷新容器)

refresh() 定义实现过程,包括:

1、创建 BeanFactory,并加载 BeanDefinition
2、获取 BeanFactory
3、在 Bean 实例化之前,执行 BeanFactoryPostProcessor (如果有扩展bean,则执行扩展的逻辑)
4、注册BeanPostProcessor的扩展点 (需要提前于其他 Bean 对象实例化之前执行注册操作)
5、提前实例化单例Bean对象

3、另外把定义出来的抽象方法,refreshBeanFactory()、getBeanFactory() 由后面的继承此抽象类的其他抽象类实现。


5、获取Bean工厂和加载资源–AbstractRefreshableApplicationContext

/**
 * @desc 获取bean工厂、加载资源
 * @Author: ljc
 * @Date: 2022/12/15 12:03
 */
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext{

    private DefaultListableBeanFactory beanFactory;

    /**
     * @desc: 实例化bean工厂、加载、注册bean定义
     **/
    @Override
    protected void refreshBeanFactory() throws BeansException {
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        loadBeanDefinition(beanFactory);
        this.beanFactory = beanFactory;
    }

    /**
     * @desc: 加载bean定义
     **/
    protected abstract void loadBeanDefinition(DefaultListableBeanFactory beanFactory);

    /**
     * @desc: 创建bean工厂
     **/
    private DefaultListableBeanFactory createBeanFactory(){
        return new DefaultListableBeanFactory();
    }

    @Override
    protected ConfigurableListableBeanFactory getBeanFactory() {
        return beanFactory;
    }
}

1、继承AbstractApplicationContext ,重写了refreshBeanFactory() 中主要是获取了 DefaultListableBeanFactory 的实例化以及对资源配置的加载操作

2、定义了抽象方法loadBeanDefinitions(beanFactory),在加载完成后即可完成对 spring.xml 配置文件中 Bean 对象的定义和注册

3、但此时资源加载还只是定义了一个抽象类方法 loadBeanDefinitions(DefaultListableBeanFactory beanFactory),继续由其他抽象类继承实现。


6、上下文中对xml配置信息的加载–AbstractXmlApplicationContext

/**
 * @desc 上下文中对xml配置信息的加载
 * @Author: ljc
 * @Date: 2022/12/15 12:12
 */
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableApplicationContext{

    // 加载bean定义
    @Override
    protected void loadBeanDefinition(DefaultListableBeanFactory beanFactory) {
        XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory, this);
        String[] configLocations = getConfigLocations();
        if (configLocations != null) {
            xmlBeanDefinitionReader.loadBeanDefinitions(configLocations);
        }
    }

    // 获取配置信息
    protected abstract String[] getConfigLocations();
}

1、继承AbstractRefreshableApplicationContext,重写loadBeanDefinition方法,通过XmlBeanDefinitionReader去加载xml配置信息、解析、注册beanDefintion

2、同时这里又留下了一个抽象类方法,getConfigLocations(),此方法是为了从入口上下文类,拿到配置信息的地址描述


7、应用上下文实现类–ClassPathXmlApplicationContext

/**
 * @desc xml应用上下文实现类
 * @Author: ljc
 * @Date: 2022/12/15 12:30
 */
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext{

    // 类文件路径
    private String[] configLoadtions;

    /**
     * @desc: 根据路径从 XML 中加载 BeanDefinition,并刷新上下文
     * @return:
     **/
    public ClassPathXmlApplicationContext(String[] configLoadtions) {
        this.configLoadtions = configLoadtions;
        refresh();
    }
    
    public ClassPathXmlApplicationContext(String configLoadtion) {
        this(new String[]{configLoadtion});

    }
    public ClassPathXmlApplicationContext() {

    }

    @Override
    protected String[] getConfigLocations() {
        return configLoadtions;
    }
}

1、ClassPathXmlApplicationContext是具体对外给用户提供的应用上下文方法

2、在继承了 AbstractXmlApplicationContext 以及层层抽象类的功能分离实现后,在此类 ClassPathXmlApplicationContext 的实现中就简单多了,主要是对继承抽象类中refresh方法的调用提供了配置文件地址信息


8、在Bean创建时完成前置和后置处理

/**
 * @desc 实例化Bean类
 * @Author: ljc
 * @Date: 2022/12/7 13:06
 */
public abstract class  AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {

    private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();

    /**
     * 创建bean
     * @param beanName
     * @param beanDefinition
     * @param args
     * @return
     * @throws BeansException
     */
    @Override
    protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException {
        Object bean = null;
        try {
            bean = createBeanInstance(beanName,beanDefinition,args);
            // 属性填充
            applyPropertyvalues(beanName,bean,beanDefinition);
            // 执行 Bean 的初始化方法和 BeanPostProcessor 的前置和后置处理方法
            bean = initializeBean(beanName, bean, beanDefinition);
        } catch (Exception e) {
            throw new BeansException("Instantiation of bean failed", e);
        }
        addSingleton(beanName,bean);
        return bean;
    }

    private Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition) {
        // 1. 执行 BeanPostProcessor Before 处理
        Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);

        // 待完成内容:invokeInitMethods(beanName, wrappedBean, beanDefinition);
        invokeInitMethods(beanName, wrappedBean, beanDefinition);

        // 2. 执行 BeanPostProcessor After 处理
        wrappedBean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
        return wrappedBean;
    }


    private void invokeInitMethods(String beanName, Object wrappedBean, BeanDefinition beanDefinition) {

    }


    /**
     * 创建实例
     * @param beanName
     * @param beanDefinition
     * @param args
     * @return
     */
    protected Object createBeanInstance(String beanName, BeanDefinition  beanDefinition, Object[] args) {
        Constructor constructorToUse  = null;
        Class beanClass = beanDefinition.getBeanClass();
        Constructor[] declaredConstructors = beanClass.getDeclaredConstructors();
        for (Constructor ctor : declaredConstructors) {
            if (args != null && ctor.getParameterTypes().length == args.length) {
                constructorToUse  = ctor;
                break;
            }
        }
        return getInstantiationStrategy().instantiate(beanDefinition,beanName,constructorToUse,args);
    }


    /**
     * 属性填充
     * @param beanName
     * @param bean
     * @param beanDefinition
     */
    protected void applyPropertyvalues(String beanName, Object bean,BeanDefinition beanDefinition) {
        try {
            PropertyValues propertyValues = beanDefinition.getPropertyValues();
            for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {
                String name = propertyValue.getName();
                Object value = propertyValue.getValue();

                if (value instanceof BeanReference) {
                    // 获取 依赖的对象实例化
                    BeanReference beanReference = (BeanReference) value;
                    value = getBean(beanReference.getBeanName());
                }
                BeanUtil.setFieldValue(bean, name, value);
            }
        } catch (BeansException e) {
            throw new BeansException("Error setting property values:" + beanName);
        }
    }

    /**
     * 获取实例化策略
     * @return
     */
    public InstantiationStrategy getInstantiationStrategy() {
        return instantiationStrategy;
    }

    // 定义实例化策略
    public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
        this.instantiationStrategy = instantiationStrategy;
    }


    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessBeforeInitialization(result, beanName);
            if (null == current) return result;
            result = current;
        }
        return result;
    }

    @Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if (null == current) return result;
            result = current;
        }
        return result;
    }
}

1、实现 BeanPostProcessor 接口后,会涉及到两个接口方法,postProcessBeforeInitialization(初始化前)、postProcessAfterInitialization(初始化后),分别作用于 Bean 对象执行初始化前后的额外处理。

2、在创建 Bean 对象时,在 createBean 方法中添加 initializeBean(beanName, bean, beanDefinition); 操作。而这个操作主要主要是对于方法 applyBeanPostProcessorsBeforeInitialization、applyBeanPostProcessorsAfterInitialization 的使用。

3、另外需要提一下,applyBeanPostProcessorsBeforeInitializationapplyBeanPostProcessorsAfterInitialization 两个方法是在接口类 AutowireCapableBeanFactory 中新增加的


二、测试

1、事先准备

public class UserDao {

    private static Map<String, String> hashMap = new HashMap<>();

    static {
        hashMap.put("10001", "ljc");
        hashMap.put("10002", "yaya");
        hashMap.put("10003", "zz");
    }

    public String queryUserName(String uId) {
        return hashMap.get(uId);
    }

}
public class UserService {

    private String uId;
    private String company;
    private String location;
    private UserDao userDao;

    public String queryUserInfo() {
        return userDao.queryUserName(uId)+", 公司:"+company+", 地点"+location;
    }


    public String getuId() {
        return uId;
    }

    public void setuId(String uId) {
        this.uId = uId;
    }

    public UserDao getUserDao() {
        return userDao;
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public String getCompany() {
        return company;
    }

    public void setCompany(String company) {
        this.company = company;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }
}

这里新增加了 company、location,两个属性信息,便于测试 BeanPostProcessor、BeanFactoryPostProcessor 两个接口对 Bean 属性信息扩展的作用


2、 实现 BeanPostProcessor 和 BeanFactoryPostProcessor

/**
 * @desc 测试BeanDefinition加载后扩展处理
 * @Author: ljc
 * @Date: 2022/12/15 14:15
 */
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService");
        PropertyValues propertyValues = beanDefinition.getPropertyValues();

        propertyValues.addPropertyValue(new PropertyValue("company","改为:网吧"));
    }
}
/**
 * @desc 初始化前后置处理
 * @Author: ljc
 * @Date: 2022/12/15 14:18
 */
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if ("userService".equals(beanName)) {
            UserService userService = (UserService) bean;
            userService.setLocation("改为:上海");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

如果你在 Spring 中做过一些组件的开发那么一定非常熟悉这两个类,本文的测试也是实现了这两个类,对实例化过程中的 Bean 对象做一些操作。


3、配置文件

spring.xml基础配置,无BeanFactoryPostProcessor、BeanPostProcessor,实现类

<?xml version="1.0" encoding="UTF-8"?>
<beans>

    <bean id="userDao" class="springframework.test.bean.UserDao"/>

    <bean id="userService" class="springframework.test.bean.UserService">
        <property name="uId" value="10001"/>
        <property name="company" value="腾讯"/>
        <property name="location" value="深圳"/>
        <property name="userDao" ref="userDao"/>
    </bean>

</beans>

增强配置,有BeanFactoryPostProcessor、BeanPostProcessor,实现类

<?xml version="1.0" encoding="UTF-8"?>
<beans>

    <bean id="userDao" class="springframework.test.bean.UserDao"/>

    <bean id="userService" class="springframework.test.bean.UserService">
        <property name="uId" value="10001"/>
        <property name="company" value="腾讯"/>
        <property name="location" value="深圳"/>
        <property name="userDao" ref="userDao"/>
    </bean>


    <bean class="springframework.test.common.MyBeanPostProcessor"/>
    <bean class="springframework.test.common.MyBeanFactoryPostProcessor"/>

</beans>

这里提供了两个配置文件

一个是不包含BeanFactoryPostProcessor、BeanPostProcessor,

另外一个是包含的。之所以这样配置主要对照验证,在运用 Spring 新增加的应用上下文和不使用的时候,都是怎么操作的


4、不用应用上下文

@Test
public void test_BeanFactoryPostProcessorAndBeanPostProcessor(){
    // 1.初始化 BeanFactory
    DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

    // 2. 读取配置文件&注册Bean
    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
    reader.loadBeanDefinitions("classpath:spring.xml");

    // 3. BeanDefinition 加载完成 & Bean实例化之前,修改 BeanDefinition 的属性值
    MyBeanFactoryPostProcessor beanFactoryPostProcessor = new MyBeanFactoryPostProcessor();
    beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);

    // 4. Bean实例化之后,修改 Bean 属性信息
    MyBeanPostProcessor beanPostProcessor = new MyBeanPostProcessor();
    beanFactory.addBeanPostProcessor(beanPostProcessor);

    // 5. 获取Bean对象调用方法
    UserService userService = beanFactory.getBean("userService", UserService.class);
    String result = userService.queryUserInfo();
    System.out.println("测试结果:" + result);
}

1、DefaultListableBeanFactory 创建 beanFactory 并使用 XmlBeanDefinitionReader 加载配置文件的方式

2、接下来就是对 MyBeanFactoryPostProcessor 和 MyBeanPostProcessor 的处理
一个是在BeanDefinition 加载完成 & Bean实例化之前,修改 BeanDefinition 的属性值
另外一个是在Bean实例化之后,修改 Bean 属性信息


测试结果

测试结果:ljc, 公司:改为:网吧, 地点改为:上海

Process finished with exit code 0

5、使用应用上下文

@Test
public void test_xml() {
    // 1.初始化 BeanFactory
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:springPostProcessor.xml");

    // 2. 获取Bean对象调用方法
    UserService userService = applicationContext.getBean("userService", UserService.class);
    String result = userService.queryUserInfo();
    System.out.println("测试结果:" + result);
}

1、使用新增加的 ClassPathXmlApplicationContext 应用上下文类,再操作起来就方便多了,这才是面向用户使用的类,在这里可以一步把配置文件交给 ClassPathXmlApplicationContext,也不需要管理一些自定义实现的 Spring 接口的类。

测试结果

测试结果:ljc, 公司:改为:网吧, 地点改为:上海

Process finished with exit code 0

这与不用应用上下文的测试结果是一样,不过现在的方式更加方便了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/93845.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

webpack学习-cdn加速,使用 Tree Shaking,提取公共代码,分割代码按需加载 使用 Prepack开启 Scope Hoisting

4-9 CDN 加速 什么是 CDN 虽然前面通过了压缩代码的手段来减小网络传输大小,但实际上最影响用户体验的还是网页首次打开时的加载等待。 导致这个问题的根本是网络传输过程耗时大,CDN 的作用就是加速网络传输。 CDN 又叫内容分发网络,通过把资源部署到世界各地,用户在访问…

Mentor-dft 学习笔记 day43-Power-Aware DRC and ATPG

Power-Aware DRC and ATPG 本章介绍用于ATPG工具的power-aware DRC和ATPG流程。Power-Aware Overview 电子行业在设计连续体的主要方面采用了低功耗特性。EDA供应商和主要半导体公司定义了常用的电力数据标准格式来描述电力需求&#xff1a;UPF和CPF。Tessent Shell supports t…

Centos7迁移Anolis OS7系统

2020年12月08日CentOS官方宣布CentOS项目将停止&#xff0c;并推出CentOS Stream项目&#xff0c;详见公告 CentOS未来将会从 RedHat Enterprise Linux(RHEL) 复刻版本的 CentOS Linux 转向 CentOS Stream。 对处于生命周期中的 CentOS 版本后续影响&#xff1a; • CentOS Lin…

Codeforces Round #838 (Div. 2) A-C题解

cf比赛链接 目录 A. Divide and Conquer 题意&#xff1a; 思路&#xff1a; 代码&#xff1a; B. Make Array Good 题意&#xff1a; 思路&#xff1a; 代码&#xff1a; C. Binary Strings are Fun&#xff08;什么疑惑题面&#xff09; 题意&#xff1a;首先的两个…

PG::Sumo

nmap -Pn -p- -T4 --min-rate1000 192.168.170.87 nmap -Pn -p 22,80 -sCV 192.168.170.87 查看80端口的页面&#xff0c;没有什么有用的信息 尝试路径爆破&#xff0c;发现了/cgi-bin目录&#xff0c;就想到了HTB中的Shocker靶机。 继续爆破 wfuzz -c -z file,/usr/share/…

03. SQL注入漏洞基础

03. SQL注入漏洞基础 SQL注入漏洞基础&#xff08;上&#xff09; /01 SQL注入的原理 SQL注入原理 SQL注入产生的原因 当Web应用向后台数据库传递SQL语句进行数据库操作时。如果对用户输入的参数没有经过严格的过滤处理&#xff0c;那么攻击者就可以构造特殊的SQL语句&…

泓德基金:以超融合构建生产及灾备环境,承载 O32 等关键业务系统

案例亮点 承载 O32、TA、估值等基金行业关键业务系统生产与灾备环境。 POC 期间对超融合应用承载能力以及数据库支撑能力分别进行验证&#xff0c;性能与稳定性均满足需求。 超融合首先作为灾备资源池部署&#xff0c;稳定运行一年后&#xff0c;转为生产资源池&#xff0c;并…

高企认定没专利?专利评分低?如何评分?

众所周知&#xff0c;高企申报是一场“持久战”&#xff0c;申报知识产权、归集研发费用、科技成果转化等工作都需要一定的准备时间。其中&#xff0c;知识产权的获取所需要的时间是最长的(两年左右)&#xff0c;对高新认定评分的影响也是最大的。因此&#xff0c;知识产权的研…

来聊一聊 ElasticSearch 最新版的 Java 客户端

可能不少小伙伴都注意到了&#xff0c;从 ElasticSearch7.17 这个版本开始&#xff0c;原先的 Java 高级客户端 Java High Level REST Client 废弃了&#xff0c;不支持了。老实说&#xff0c;ElasticSearch 算是我用过的所有 Java 工具中&#xff0c;更新最为激进的一个了&…

Unity中的Mask组件增加DrawCall的原因

Unity中的Mask组件增加DrawCall的原因 简介 常说mask组件不要常用&#xff0c;因为会增加drawcall&#xff0c;增加性能消耗&#xff1b;当然作为一个需要背八股文的同学而言&#xff0c;仅仅知道会增加性能消耗是不够的&#xff0c;所以这里简单看下其原理。 首先看下在Uni…

监控系列(三)自定义DM采集项(exporter)+主机监控+grafana展示

一、概括 本篇不涉及达梦数据库搭建&#xff0c;操作环境需提前准备prometheus以及grafana的搭建&#xff0c;请跳转到前文查看 监控系列&#xff08;一&#xff09;DM8PrometheusGrafana搭建 监控系列&#xff08;二&#xff09;Dem对接Prometheusgrafana显示 自定义的采集…

基于数字孪生技术的智慧变电站Web3D可视化系统

今天为大家分享一个采用 数维图 的 Sovit3D 构建轻量化 3D 可视化场景的案例——数字孪生智慧变电站三维可视化系统。多维度呈现变电站场景&#xff0c;实现变电站运行态势的实时监测&#xff0c;运维设备、控制系统和信息系统的互联互通。加强变电站设备的全状态感知力与控制力…

03-MySQL查询数据

目录 DQL语言 单表查询 AS子句 DISTINCT关键字的使用 WHERE条件语句 逻辑操作符 比较操作符 BETWEEN范围查询 LIKE模糊查询 使用IN进行范围查询 NULL空值条件查询 连接查询&#xff08;多表查询&#xff09; INNER JOIN内连接 等值和非等值的连接查询 外连接 JOIN对比…

49.Python的while循环

49.Python的while循环 文章目录49.Python的while循环1. 什么是循环2. 什么是while循环3.课题导入4.while循环语法5.while循环执行流程6. if和while的区别7.课堂练习1. 什么是循环 【循环的百度释义】 特指运行一周而回到原处&#xff0c;再转。 反复地连续地做某事。 【循环…

新征程-猿如意试用一波!

猿如意传送门&#xff08;必带&#xff09; 猿如意下载地址&#xff1a;猿如意-程序员的如意兵器,工具代码,一搜就有 猿如意使用了几次了&#xff0c;今天来想分享一下我对于猿如意的使用感受吧&#xff01;&#xff01; 先说结论&#xff1a;值得每个程序员都在电脑里安装一…

MySQL的基础架构简述

文章目录一、一条SQL查询语句是如何执行的1、连接器2、查询缓存3、分析器4、优化器5、执行器一、一条SQL查询语句是如何执行的 开篇先上基本架构示意图&#x1f917;&#xff1a; 大体来说&#xff0c;MySQL可以分为 Server 层和存储引擎两部分。 Server 层包括连接…

大一作业HTML网页作业 HTML校园篮球网页作业(12个页面)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

前沿系列--简述Diffusion Model 扩散模型(无代码版本)

文章目录前言why扩散简述how如何扩散逆向过程小结流程训练过程预测过程总结前言 OK&#xff0c;今天的话&#xff0c;我们来搞一下这个扩散模型&#xff0c;来对这个玩意进行一个简单的了解&#xff0c;因为这个也是目前还算比较前沿的东西&#xff0c;也挺有用的&#xff0c;…

CSAPP-Lab2 BombLab解析

文章目录ReferencePhase1Phase2Phase3Phase4Phase5Phase6Part1Part2Part3Part4Part5Part6SecretBombSummaryReference GDB Command Reference - disassemble command&#xff1a;怎么使用GDB进行反汇编调试GDB X CommandGDB and Debugging&#xff1a;GDB上手教程和如何进行de…

大一作业HTML网页作业 HTML CSS制作二十四节气网页

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…