Spring实战系列(四)-动态注入接口Bean

【Spring Boot 3】动态注入和移除Bean 本文介绍开发Spring Boot应用如何动态注入及移除Bean实例。获取;通过获取;通过构建;调用的方法注入。 阅读详情

"对于Spring框架,现实公司使用的非常广泛,但是由于业务的复杂程度不同,了解到很多小伙伴们利用Spring开发仅仅是利用了Spring的IOC,即使是AOP也很少用,但是目前的Spring是一个大家族,形成了一个很大的生态,覆盖了我们平时开发的方方面面,抛开特殊的苛刻要求之外,Spring的生态其实已经很全面了,所以在此开个系列来研究下Spring提供给我们的一些平时不太却又很实用的内容。"

    上一篇我们分析了BeanPostProcessor的基本使用,接下来我们分析下如何使用该类实现动态的接口注入,示例说明:在BeetlSQL框架中,在使用自动扫描注入时,我们通常只需要配置上要扫描的包路径,然后在该路径下声明对应的Dao接口类,这些接口类都默认继承BaseMapper接口类,然后我们在使用这些Dao类的时候,直接根据类型注入(@Autowired)即可使用,这个其实和Mybatis的那一套相似,也和Spring自身的Spring-data框架也类似。这个经常用于框架的开发,那么我就该部分的实现做相应的解释,这三个框架具体实现可能有差距,感兴趣的小伙伴自行去查看源码,我会以一个很简单的例子来讲解大概的实现逻辑。

    问题描述:

      继承Spring框架,实现声明某个自定义接口(UserMapper),改接口继承通用接口BaseMapper,(通用接口BaseMapper有默认的实现类),实现通过类型注入UserMapper类,然后通过Spring框架的上下文类(ApplicationContext实现类)的getBean()方法拿到UserMapper类来调用内部提供的方法。

 1、声明BaseMapper接口类

public interface BaseMapper {

    /**
     * @param value
     */
    public void add(String value);

    /**
     * @param key
     */
    public void remove(String key);
}

2、默认BaseMapper实现类:CustomBaseMapper

public class CustomBaseMapper implements BaseMapper {
    private final Logger logger = Logger.getLogger(this.getClass().getName());
    private List<String> dataList = new CopyOnWriteArrayList<>();

    /**
     * @param value
     */
    @Override
    public void add(String value) {
        logger.info("添加数据:" + value);
        dataList.add(value);
    }

    /**
     * @param key
     */
    @Override
    public void remove(String key) {
        if (dataList.isEmpty())
            throw new IllegalArgumentException("Can't remove because the list is Empty!");

    }
}

接下来是继承Spring的核心代码

3、首先我们要先定义一个扫描某路径下的类,该类继承ClassPathBeanDefinitionScanner,自定义扫描类:DefaultClassPathScanner

public class DefaultClassPathScanner extends ClassPathBeanDefinitionScanner {

    private final String DEFAULT_MAPPER_SUFFIX = "Mapper";

    public DefaultClassPathScanner(BeanDefinitionRegistry registry) {
        super(registry, false);
    }

    private String mapperManagerFactoryBean;

    /**
     * 扫描包下的类-完成自定义的Bean定义类
     *
     * @param basePackages
     * @return
     */
    @Override
    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
        // 如果指定的基础包路径中不存在任何类对象,则提示
        if (beanDefinitions.isEmpty()) {
            logger.warn("系统没有在 '" + Arrays.toString(basePackages) + "' 包中找到任何Mapper,请检查配置");
        } else {
            processBeanDefinitions(beanDefinitions);
        }
        return beanDefinitions;
    }

    /**
     * 注册过滤器-保证正确的类被扫描注入
     */
    protected void registerFilters() {
        addIncludeFilter(new TypeFilter() {
            @Override
            public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
                    throws IOException {
                String className = metadataReader.getClassMetadata().getClassName();
                //TODO 这里设置包含条件-此处是个扩展点,可以根据自定义的类后缀过滤出需要的类
                return className.endsWith(DEFAULT_MAPPER_SUFFIX);
            }
        });
        addExcludeFilter(new TypeFilter() {
            @Override
            public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
                    throws IOException {
                String className = metadataReader.getClassMetadata().getClassName();
                return className.endsWith("package-info");
            }
        });
    }

    /**
     * 重写父类的判断是否能够实例化的组件-该方法是在确认是否真的是isCandidateComponent
     * 原方法解释:
     * 确定给定的bean定义是否有资格成为候选人。
     * 默认实现检查类是否不是接口,也不依赖于封闭类。
     * 以在子类中重写。
     *
     * @param beanDefinition
     * @return
     */
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        // 原方法这里是判断是否为顶级类和是否是依赖类(即接口会被排除掉-由于我们需要将接口加进来,所以需要覆盖该方法)
        return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();
    }

    /**
     * 扩展方法-对扫描到的含有BeetlSqlFactoryBean的Bean描述信息进行遍历
     *
     * @param beanDefinitions
     */
    void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
        GenericBeanDefinition definition;
        for (BeanDefinitionHolder holder : beanDefinitions) {
            definition = (GenericBeanDefinition) holder.getBeanDefinition();
            String mapperClassName = definition.getBeanClassName();
            // 必须在这里加入泛型限定,要不然在spring下会有循环引用的问题
            definition.getConstructorArgumentValues().addGenericArgumentValue(mapperClassName);
            //依赖注入
            definition.getPropertyValues().add("mapperInterface", mapperClassName);
            // 根据工厂的名称创建出默认的BaseMapper实现
            definition.getPropertyValues().add("mapperManagerFactoryBean", new RuntimeBeanReference(this.mapperManagerFactoryBean));
            definition.setBeanClass(BaseMapperFactoryBean.class);
            // 设置Mapper按照接口组装
            definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
            logger.info("已开启自动按照类型注入 '" + holder.getBeanName() + "'.");
        }
    }

    public void setMapperManagerFactoryBean(String mapperManagerFactoryBean) {
        this.mapperManagerFactoryBean = mapperManagerFactoryBean;
    }
}

4、核心的接口实现类:BaseMapperFactoryBean

public class BaseMapperFactoryBean<T> implements FactoryBean<T>, InitializingBean, ApplicationListener<ApplicationEvent>, ApplicationContextAware {
    /**
     * 要注入的接口类定义
     */
    private Class<T> mapperInterface;

    /**
     * Spring上下文
     */
    private ApplicationContext applicationContext;

    //也因该走工厂方法注入得来

    private BaseMapper mapperManagerFactoryBean;

    public BaseMapperFactoryBean(Class<T> mapperInterface) {
        this.mapperInterface = mapperInterface;
    }

    @Override
    public T getObject() throws Exception {
        //采用动态代理生成接口实现类,核心实现
        return (T) Proxy.newProxyInstance(applicationContext.getClassLoader(), new Class[]{mapperInterface}, new MapperJavaProxy(mapperManagerFactoryBean, mapperInterface));
    }

    @Override
    public Class<?> getObjectType() {
        return this.mapperInterface;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        //TODO 判断属性的注入是否正确-如mapperInterface判空
        if (null == mapperInterface)
            throw new IllegalArgumentException("Mapper Interface Can't Be Null!!");
    }

    /**
     * Handle an application event.
     *
     * @param event the event to respond to
     */
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        //TODO 可依据事件进行扩展
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public void setMapperInterface(Class<T> mapperInterface) {
        this.mapperInterface = mapperInterface;
    }


    public void setMapperManagerFactoryBean(BaseMapper mapperManagerFactoryBean) {
        this.mapperManagerFactoryBean = mapperManagerFactoryBean;
    }
}

5、定义默认的BaseMapper的FactoryBean-MapperManagerFactoryBean

public class MapperManagerFactoryBean implements FactoryBean<BaseMapper>, InitializingBean, ApplicationListener<ApplicationEvent> {

    @Override
    public BaseMapper getObject() throws Exception {
        return new CustomBaseMapper();
    }

    @Override
    public Class<?> getObjectType() {
        return BaseMapper.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        //TODO 判断属性的注入是否正确
    }

    /**
     * Handle an application event.
     *
     * @param event the event to respond to
     */
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println(event.toString());
    }
}

6、核心的java动态代理类:MapperJavaProxy

public class MapperJavaProxy implements InvocationHandler {

    private BaseMapper baseMapper;

    private Class<?> interfaceClass;

    public MapperJavaProxy(BaseMapper baseMapper, Class<?> interfaceClass) {
        this.baseMapper = baseMapper;
        this.interfaceClass = interfaceClass;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (!interfaceClass.isInterface()) {
            throw new IllegalArgumentException("mapperInterface is not interface.");
        }

        if (baseMapper == null) {
            baseMapper = new CustomBaseMapper();
        }
        return method.invoke(baseMapper, args);
    }
}

7、调用时的核心配置类:DefaultClassRegistryBeanFactory

public class DefaultClassRegistryBeanFactory implements ApplicationContextAware, BeanDefinitionRegistryPostProcessor, BeanNameAware {

    private String scanPackage;

    private String beanName;

    private String mapperManagerFactoryBean;

    private ApplicationContext applicationContext;

    public String getScanPackage() {
        return scanPackage;
    }

    public void setScanPackage(String scanPackage) {
        this.scanPackage = scanPackage;
    }

    public String getMapperManagerFactoryBean() {
        return mapperManagerFactoryBean;
    }

    public void setMapperManagerFactoryBean(String mapperManagerFactoryBean) {
        this.mapperManagerFactoryBean = mapperManagerFactoryBean;
    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        if (StringUtils.isEmpty(this.scanPackage)) {
            throw new IllegalArgumentException("scanPackage can't be null");
        }
        String basePackage2 = this.applicationContext.getEnvironment().resolvePlaceholders(this.scanPackage);
        String[] packages = StringUtils.tokenizeToStringArray(basePackage2, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
        DefaultClassPathScanner defaultClassPathScanner = new DefaultClassPathScanner(beanDefinitionRegistry);
        defaultClassPathScanner.setMapperManagerFactoryBean(mapperManagerFactoryBean);
        defaultClassPathScanner.registerFilters();

        defaultClassPathScanner.doScan(packages);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void setBeanName(String name) {
        this.beanName = name;
    }
}

8、调用测试

   8.1、假设你在包目录:colin.spring.basic.advanced.inject.dao下声明自定义的类UserMapper

public interface UserMapper extends BaseMapper {
}

8.2、声明配置类:ClassRegistryBeanScannerConfig

@Configuration
public class ClassRegistryBeanScannerConfig {

    @Bean(name = "mapperManagerFactoryBean")
    public MapperManagerFactoryBean configMapperManagerFactoryBean() {
        MapperManagerFactoryBean mapperManagerFactoryBean = new MapperManagerFactoryBean();
        return mapperManagerFactoryBean;
    }

    @Bean
    public DefaultClassRegistryBeanFactory configDefaultClassRegistryBeanFactory() {
        DefaultClassRegistryBeanFactory defaultClassRegistryBeanFactory = new DefaultClassRegistryBeanFactory();
        defaultClassRegistryBeanFactory.setScanPackage("colin.spring.basic.advanced.inject.dao");
        defaultClassRegistryBeanFactory.setMapperManagerFactoryBean("mapperManagerFactoryBean");
        return defaultClassRegistryBeanFactory;
    }
}

8.3、测试调用

  public static void main(String[] args) {
        AnnotationConfigApplicationContext acApplicationCOntext = new AnnotationConfigApplicationContext("colin.spring.basic.advanced.inject");
        UserMapper userMapper = acApplicationCOntext.getBean(UserMapper.class);
        userMapper.add("lalaldsf");
        acApplicationCOntext.stop();
    }

总结:

此处对于BeanPostProcessor接口的调用应该属于高级应用了,该思路常用来解决扩展或集成Spring框架,其核心的思路可以分为以下几步:

   1、自定义实现类路径扫描类,决定哪些类应该被注入进Spring容器。

   2、采用Java动态代理来动态实现对于声明接口类的注入。

   3、实现BeanDefinitionRegistryPostProcessor,在Spring初始化初期将需要扫描导入Spring容器的类进行注入。

  (PS:需要对Spring的BeanDefinition类有一定的了解,下一张我们来分析该类的)

Spring动态注册Bean 一、前言 一般而言,使用静态配置信息,即可由Spring容器生成我们需要的Bean。但是在一些场景下,我们需要Spring容器根据我们的配置信息动态的生成Bean,这时就需要将Bean动态的注册到Spring容器中去。 一般而言,我们使用@Componment、@Service等注解,就可以向Spring容器注册Bean,下面介绍自动的动态注入Bean到Spring容器。 具体的应用场景,可以参考我写的一个简单快捷的rocketmq-spring-boot-start里的实现。 二、设计测试的Bean 1、 阅读详情

相关推荐

Spring——Bean注入几种方式(放入容器)

Spring系列初体验,使用Spring怎么能不知道这几种将Bean放入容器中的方法呢?XML、注解、实现接口..

共勉 1万+

浅析代理bean 注入原理

大家不知道有没有好奇过各种spring框架中的神奇功能是怎么实现的,例如Feign 的接口,和Jpa 的接口,Spring 是如何驱动实现的呢。下面我来分析一下 在了解FeignClient 注解中发现,FeignClient 注解的接口都是Proxy 类。那到底是如何生成的呢? spring在注入bean的时候,会根据容器中bean 的类型或者name 来匹配bean 的注入, 但是interf...

rainful__的博客 1053

Mybatis通用Mapper的CRUD操作封装BaseService

前言 使用Mybatis的开发者,大多数都会遇到一个问题,就是要写大量的SQL在xml文件中,除了特殊的业务逻辑SQL之外,还有大量结构类似的增删改查SQL。而且,当数据库表结构改动时,对应的所有SQL以及实体类都需要更改。这工作量和效率的影响或许就是区别增删改查程序员和真正程序员的屏障。这时,通用Mapper便应运而生…… 如何实现 这里我们使用tk.Mapper实现,编写Base...

绎荣 4573

1.Spring 学习 注入Bean 方式

注入bean的方式 1 xml 注入 @Data public class UserEnity { private String id; private String name; @Override public String toString() { return "UserEnity{" + "id='" + id + '\'' + ", name='" + name +

beyondwenhao 385

创建动态代理对象bean,并动态注入到spring容器中

使用过Mybatis的同学,应该都知道,我们只需要编写mybatis对应的接口和mapper XML文件即可,并不需要手动编写mapper接口的实现。这里mybatis就用到了JDK动态代理,并且将生成的接口代理对象动态注入到Spring容器中。 这里涉及到几个问题。也许有同学会有疑问,我们直接编写好类,加入@Component等注解不是可以注入了吗?或者在配置类(@Configuration)...

lichuangcsdn的博客 3万+

Spring Boot通过ImportBeanDefinitionRegistrar动态注入Bean

在阅读Spring Boot源码时,看到Spring Boot中大量使用ImportBeanDefinitionRegistrar来实现Bean的动态注入。它是Spring中一个强大的扩展接口。本篇文章来讲讲它相关使用。 Spring Boot中的使用 在Spring Boot 内置容器的相关自动配置中有一个ServletWebServerFactoryAutoConfiguration类。该类的...

程序新视界 4863

Spring Boot 的 3 种动态 Bean 注入技巧

/ 自定义条件判断逻辑@Override// 获取注解属性// 获取当前环境// 检查是否匹配// 自定义条件注解@Bean@Bean通过合理选择和组合这些技巧,我们可以构建更加灵活、模块化和可扩展的 Spring Boot 应用。关键是根据实际需求选择合适的技术,保持代码的简洁和可维护性。

z1ztai的博客 2214

GNSS数据处理(一)——开源软件RTKLIB与G-Nut/Anubis实战入门

本文详细介绍了GNSS数据处理的开源软件RTKLIB与G-Nut/Anubis的实战入门指南。从软件安装、数据获取到静态短基线解算,逐步讲解操作技巧与常见问题排查,帮助测绘与地质监测人员快速掌握GNSS数据处理技术,提升工作效率。

weixin_30733003的博客 133

Spring-Bean的动态注入

如果有两个类实现了同一个接口,那么@Autowired实现哪个类的实例,取决于你如何使用@Qualifier注解来指定要注入的实现类。如果没有指定@Qualifier注解来区分它们,那么@Autowired注入时会报错,因为Spring无法确定要注入哪个实现类。@Autowired是Spring框架中的一个注解,它可以对类成员变量、方法及构造函数进行标注,让 Spring 完成 bean 自动装配的工作。在yml文件中,使用@Qualifier注解来指定要注入的实现类。这样就可以指定要注入AImpl了。

Cartel的专栏 1630

Word论文插入带有方括号序号的参考文献——尾注+交叉引用

文章目录1. 尾注功能2. 为参考文献的序号添加方括号3. 调整参考文献前的序号大小4. 重复引用同一参考文献5. 将交叉引用的序号改为带有方括号的上标序号格式6. 删除参考文献前的尾注横线 1. 尾注功能 首先使用尾注功能顺序插入参考文献,暂时不考虑方括号问题,具体操作如下: ① 将光标放在需要插入参考文献角标的地方 ② 在word菜单栏,“引用-脚注部分右下角箭头”(用来设置尾注格式) ③如...

Your_Raymond的博客 9万+

SAP PP工艺路线Routing保姆级配置指南:从CA01创建到替代/并行顺序实战

本文详细解析SAP PP模块中工艺路线(Routing)的配置与应用,从基础创建(CA01)到高级功能如替代顺序和并行顺序的实战操作。通过真实案例演示,帮助用户掌握SAP PP工艺路线的精细化管理,提升生产流程效率。

weixin_30898555的博客 388

Spring:三种实例化bean的方式

Spring的实例化Bean有三种方式:     使用类构造器直接实例化  使用静态工厂的方法实例化  使用实例工厂方法实例化   三种方式对应的配置如下 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-insta

zhang1206214477的专栏 740

2026年数字IC设计华为笔试带答案解析

这篇文章是一份数字IC设计工程师笔试的试卷结构和部分题目解析。试卷包含单选题31题(每题2分)、多选题10题(每题4分)和简答/编程题4题(每题7分),总分130分,考试时长120分钟。 摘要重点: 试卷涵盖数字IC设计的关键知识点,包括Verilog语法、时序逻辑、状态机设计、跨时钟域处理等; 题目解析详细说明了各选项的正确性,如非阻塞赋值特性(D错误)、功耗影响因素(C与组合逻辑级数弱相关)等; 包含实际工程问题,如DDR4接口电平(SSTL-1.2)、卡诺图变量排序(格雷码)等; 部分题目考察基础概念

Open 369

spring之动态注册bean

前言 一般而言,我们都知道,在启动一个spring/springboot项目时,随着ioc容器的加载,会向容器中注册许多我们在程序中已经定义好的bean,我们平时注册bean的方式如下: xml方式: <beans>//Bean定义的开始和结束 <import resource=“resource1.xml” />//导入其他配置文件Bean的定义 <import resource=“resource2.xml” /> <bean id=

weixin_41979002的博客 8261

YOLOv8模型轻量化实战:基于稀疏化剪枝与L1正则化的高效目标检测模型优化-附源码

本文提出一种YOLOv8轻量化方案,通过L1正则化稀疏化训练和动态阈值通道剪枝,在边缘计算场景中优化模型性能。方案分三步:首先通过L1正则诱导权重稀疏化并动态衰减系数;然后基于BN层权重统计进行通道剪枝,保留80%关键通道;最后对剪枝模型微调恢复精度。在COCO128数据集上验证,模型体积压缩40%,推理速度提升2.3倍,mAP仅下降0.4%,实现了精度与效率的平衡。该方案为移动端部署提供了可行的轻量化技术路径。

m0_64661770的博客 479

【工业级视觉实战】海康威视SDK + Python + YOLOv11:零延迟目标追踪系统落地指南

要在 Python 中调用海康 DLL,首先得把 C++ 的结构体 1:1 翻译过来。这是很多开发者踩坑最深的地方(指针错误、内存溢出)。import sys# 根据操作系统加载库else:# 定义设备信息结构体 (对应 C++ LPNET_DVR_DEVICEINFO_V30)("sSerialNumber", ctypes.c_byte * 48), # 序列号("byAlarmInPortNum", ctypes.c_byte), # 报警输入个数。

BUG猿的博客 227

动态注册bean到spring容器中

spring动态注册bean到spring容器中

haohaounique的博客 763

【Simulink教程案例18】基于simulink的基础OFDM+64QAM发射接收链路仿真

OFDM(Orthogonal Frequency Division Multiplexing)即正交频分复用技术,实际上OFDM是MCM(Multi Carrier Modulation),多载波调制的一种。通过频分复用实现高速串行数据的并行传输, 它具有较好的抗多径衰落的能力,能够支持多用户接入。OFDM技术由MCM(Multi-Carrier Modulation,多载波调制)发展而来。OFDM技术是多载波传输方案的实现方式之一,它的。

FPGA/MATLAB学习教程/源码/项目合作开发 1988

在Spring中注入动态代理Bean

下面仿照Mapper的实现原理来自定义注解和代理工厂,实现自定义注入动态代理Bean。Class

xiaoyi52的专栏 2466

1-Wire 单总线硬件结构及软件时序分析(实测波形+C代码分析)

1根线就可以通信,是不是很神奇?因为其节省I/O口的优点而被广泛使用!

记得诚 1万+

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Spring中接口的bean是如何注入,@service 为什么不能用在interface上

1、 Spring中接口的bean是如何注入的 大家都知道@Service注入的是实现类serviceImpl,那使用时怎么能获取到接口,而且还能调用到实现类的方法。 其中只注入了实现类serviceImpl的bean,接口只是用来接收的。这里就要说到@Autowired/@Resource的注入原理:@Autowired是Spring的注解,Autowired默认先按byType,如果发现找到多个bean,则再按照byName方式比对,如果还有多个bean,则报错Caused by: org.spring

GGHuWei的博客 3256

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

spring源码解读(二)

接着上一篇文章,首先我们需要解决如何解决不修改spring源码的情况下,使注解在接口上生效? 根据前一篇文章分析,使注解不在接口上生效的原因是因为ClassPathScanningCandidateComponentProvider的isCandidateComponent的方法 protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { AnnotationMetadata metadata =

qq_38081917的博客 981

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Spring中接口注入的三种方式

  Type1 接口注入  我们常常借助接口来将调用者与实现者分离。如:  public class ClassA {private InterfaceB clzB;public init() {Ojbect obj =Class.forName(Config.BImplementation).newInstance();clzB = (InterfaceB)obj;}……}  上面的

elimago的专栏 1298

Java的3种动态代理

动态代理创建需要代理的接口和实现类JDK代理创建代理类实现CGlib代理创建代理类实现springAop代理基于xml方式创建xml通知类创建ApplicationContext.xml测试基于注解的AOP实现添加切面依赖创建注解通知类在配置文件创建bean和开启自动扫描测试 创建需要代理的接口和实现类 JDK代理 创建代理类 代理类需要实现InvocationHandler接口的invoke方法 public class JDKProxy implements InvocationHandler {

qq_32018763的博客 1685

SpringBoot整合通用Mapper

SpringBoot整合Mybatis通用Mapper项目目录结构依赖添加配置文件信息新建一个通用的Mapper接口扫描Mapper测试 这里BaseMapper接口要继承: tk.mybatis.mapper.common.Mapper tk.mybatis.mapper.common.MySqlMapper 这个接口不能被 @MapperScan 扫描 具体代码如下:

进击的小猴 1632

SpringBoot整合mybatis通用Mapper+自定义通用Mapper方法

最近公司在用的通用mapper,自己感兴趣,然后就来搭建了一个springboot项目试验通用mapper 这个项目是国内的大神写的一个mybatis插件,里面有很多的增删改查方法 官方解释的是通用mapper支持3.2.4以及以上的版本 首先引入pom <!--Mybatis --> <dependency> <groupId>org.my...

程序员 6万+
上一篇: Spring实战系列(三)-BeanPostProcessor的妙用
轻鸿飘羽
博客等级 码龄16年 124粉丝 74原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值