news 2026/6/15 21:07:09

自定义starter,扫描指定注解的bean

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
自定义starter,扫描指定注解的bean

自定义starter

相当于自己根据配置信息,生成了一个默认的bean,

  1. 导入依赖:
<?xml version="1.0" encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.5.10</version><relativePath/><!-- lookup parent from repository --></parent><groupId>com.cj</groupId><artifactId>hello-spring-boot-starter</artifactId><version>0.0.1-SNAPSHOT</version><name>hello-spring-boot-starter</name><description>hello-spring-boot-starter</description><url/><licenses><license/></licenses><developers><developer/></developers><scm><connection/><developerConnection/><tag/><url/></scm><properties><java.version>17</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><annotationProcessorPaths><path><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId></path><path><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></path></annotationProcessorPaths></configuration></plugin></plugins></build></project>

将springboot启动类,测试类删掉,,将maven打包成jar的配置删掉,,
2. 自定义一个配置类,,来定义配置

packagecom.cj.hellospringbootstarter;importlombok.Data;importorg.springframework.boot.context.properties.ConfigurationProperties;@ConfigurationProperties(prefix="mytest")@DatapublicclassHelloProperties{privateStringid;privateStringname;privateStringaddress;}
  1. 通过这个配置加载一个默认的 Bean
@Data@NoArgsConstructorpublicclassHelloService{privateStringname;privateStringaddress;publicHelloService(Stringname,Stringaddress){this.name=name;this.address=address;}}
@Configuration@ComponentScan@EnableConfigurationProperties(HelloProperties.class)publicclassHelloServiceAutoConfiguration{@AutowiredprivateHelloPropertieshelloProperties;@BeanpublicHelloServicehelloService(){returnnewHelloService(helloProperties.getName(),helloProperties.getAddress());}}

容器中就有这个默认的 HelloService的bean,,

  1. 设置自动装配
    springboot3是在META-INF/spring文件夹下创建org.springframework.boot.autoconfigure.AutoConfiguration.imports这个文件,,
    填入自动配置类的全限定类名

springboot2是在META-INF下面创建spring.factories

  1. 打包使用
<dependency><groupId>com.cj</groupId><artifactId>hello-spring-boot-starter</artifactId><version>0.0.1-SNAPSHOT</version></dependency>
@RestController@LogpublicclassHelloController{@AutowiredHelloServicehelloService;@GetMapping("/hello")publicHelloServicegetHelloService(){returnhelloService;}}

自定义一个注解,写在starter里面,动态的增强被标注这个注解的类,,,
可以用spring中BeanPostProcessor: spring完成 实例化,配置,,, 在初始化bean的前后,可以实现一些自定义的配置,有两个方法:

  • postProcessBeforeInitialization : bean初始化之前调用
  • postProcessAfterInitialization: bean初始化之后调用

如果想增强指定的注解标注的类,,就可以写在BeanPostProcessor中,拦截指定注解,增强:

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public@interfaceLog{/** * 是否打印参数 * @return */booleanprintArgs()defaulttrue;booleanprintResult()defaulttrue;/** * 是否打印方法耗时 * @return */booleanprintCostTime()defaulttrue;}
packagecom.cj.hellospringbootstarter.annotation;importorg.springframework.beans.BeansException;importorg.springframework.beans.factory.config.BeanPostProcessor;importorg.springframework.cglib.proxy.Callback;importorg.springframework.cglib.proxy.Enhancer;importorg.springframework.cglib.proxy.MethodInterceptor;importorg.springframework.cglib.proxy.MethodProxy;importorg.springframework.stereotype.Component;importjava.lang.reflect.Method;importjava.util.Arrays;/** * 对@Log 标注的 bean进行统一的 增强 * * * BeanPostProcessor : spring完成实例化,配置,初始化一个bean之后,,可以实现一些自定义的逻辑 * - postProcessBeforeInitialization : bean初始化之前调用 * - postProcessAfterInitialization : bean初始化之后调用 */@ComponentpublicclassLogBeanPostProcessorimplementsBeanPostProcessor{@OverridepublicObjectpostProcessAfterInitialization(Objectbean,StringbeanName)throwsBeansException{Class<?>beanClass=getTargetClass(bean);// 是否标记了 @Log注解if(beanClass.isAnnotationPresent(Log.class)){LoglogAnnotation=beanClass.getAnnotation(Log.class);ObjectenhanceBean=createLogEnhanceProxy(bean,beanClass,logAnnotation);returnenhanceBean;}returnbean;}privateObjectcreateLogEnhanceProxy(ObjecttargetBean,Class<?>targetClass,LoglogAnnotation){Enhancerenhancer=newEnhancer();enhancer.setSuperclass(targetClass);// MethodInterceptor : cglib的方法拦截器,,当你调任何方法的时候,都会执行这个enhancer.setCallback(newMethodInterceptor(){@OverridepublicObjectintercept(Objectobj,Methodmethod,Object[]args,MethodProxyproxy)throwsThrowable{// 跳过Object的基础方法if(isObjectBaseMethod(method)){returnproxy.invokeSuper(obj,args);}try{if(logAnnotation.printArgs()){System.out.printf("[日志增强]%s.%s()入参:%s%n",targetClass.getSimpleName(),method.getName(),Arrays.toString(args));}longstartTime=System.currentTimeMillis();Objectresult=proxy.invokeSuper(obj,args);if(logAnnotation.printCostTime()){longendTime=System.currentTimeMillis();System.out.printf("[日志耗时]%s.%s() 耗时%s",targetClass.getSimpleName(),method.getName(),startTime-endTime);}returnresult;}catch(Throwablee){System.out.printf("日志增强失败 %s.%s() 异常为:%s",targetClass.getSimpleName(),method.getName(),e.getMessage());throwe;}};});ObjectenhancedBean=enhancer.create();System.out.println("增强完成"+targetClass.getName());returnenhancedBean;}/** * 获取bean的真实类型 * @param bean * @return */privateClass<?>getTargetClass(Objectbean){Class<?>clazz=bean.getClass();// 如果是CGLIB代理类,,获取父类if(clazz.getName().contains("$$EnhancerByCGLIB$$")){returnclazz.getSuperclass();}returnclazz;}privatebooleanisObjectBaseMethod(Methodmethod){// 获取声明该方法的类Class<?>declaringClass=method.getDeclaringClass();// method.getDeclaringClass()returndeclaringClass==Object.class&&(method.getName().equals("toString")||method.getName().equals("hashCode")||method.getName().equals("equals"));}}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/15 12:32:22

强烈安利MBA必用TOP10 AI论文写作软件

强烈安利MBA必用TOP10 AI论文写作软件 2026年MBA必备AI论文写作工具测评&#xff1a;为何需要这份榜单&#xff1f; MBA学习过程中&#xff0c;论文写作是一项核心任务&#xff0c;而传统方式往往面临效率低、格式复杂、内容质量参差不齐等问题。随着AI技术的不断进步&#xff…

作者头像 李华
网站建设 2026/6/15 16:48:15

探索整流器与逆变器的协同应用:从原理到实践

整流器逆变器。 前级采用PWM整流器&#xff0c;采用双闭环前馈解耦控制&#xff0c;实现并网单位功率因数&#xff0c;稳定直流电压。 后级采用两电平逆变器&#xff0c;通过双闭环前馈解耦控制&#xff0c;稳定输出电压。 整个仿真环境完全离散化&#xff0c;运行时间更快&…

作者头像 李华
网站建设 2026/6/15 13:36:07

基于有效磁链的无传感器控制模型探索

该模型基于有效磁链进行无传感器控制&#xff0c;为了改善磁链观测器的低速性能&#xff0c;提高低速下观测精度&#xff0c;使用电压电流混合模型&#xff0c;其运行原理为&#xff1a;使用电压模型获取定子磁链&#xff0c;经过有效磁链转化后得到转子磁链&#xff0c;通 过反…

作者头像 李华
网站建设 2026/6/15 13:29:26

永磁同步模型中的电流预测控制与广义预测控制(速度环)探索

永磁同步模型电流预测控制广义预测控制(速度环&#xff09; 速度环预测控制采用广义预测与扩展状态观测器结合&#xff0c;提高系统鲁棒性和稳态特性。 电流环采用预测控制双矢量改进算法。 含有对应学习文献 在永磁同步电机&#xff08;PMSM&#xff09;控制系统中&#xff0c…

作者头像 李华
网站建设 2026/6/15 13:31:07

从数据库到智能体:教育企业如何构建自己的“数字大脑”?

在近期一场顶级技术大会上&#xff0c;“智能体结构”成为焦点。会议指出&#xff0c;未来内容不是写出来的&#xff0c;而是从智能系统中“生长”出来的。这对于依赖内容与服务的教育行业而言&#xff0c;启示深远。创客匠人作为教育数字化领域的长期陪伴者&#xff0c;观察到…

作者头像 李华
网站建设 2026/6/15 14:29:01

MetaHuman 穿鞋 学习笔记

目录 隐藏衣服: 右侧 Details 搜索框输入:hidden 然后,勾选:Hidden In Game 给 MetaHuman 穿静态网格鞋子(Static Mesh Shoes),本质上就是: 把「静态鞋子」 → 变成「跟随角色骨骼的 Skeletal Mesh」,再绑定到脚骨。 我按 最实用路线 给你讲(适合你现在搞 MetaHum…

作者头像 李华