当前位置: 首页 > news >正文

自定义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"));}}
http://www.jsqmd.com/news/322309/

相关文章:

  • 基于高斯烟羽模型的MATLAB实现代码
  • 基于 SO - GRU 的数据回归预测:探索 2022 最新智能优化算法
  • 2026安徽祛痘加盟机构推荐:祛痘效果/祛斑祛痘/祛痘产品/祛痘招商机构精选。
  • LangChain提示词
  • mdadm的配置及故障处理
  • 日照市英语雅思培训机构推荐 2026权威测评出国雅思辅导机构口碑榜单
  • 日照市英语雅思培训机构推荐;2026权威测评出国雅思辅导机构口碑榜单
  • Qt Creator中修改源文件编码
  • 企业展厅设计Top5服务商及适配指南,凡拓数创为何受众多客户青睐?
  • 济宁市英语雅思培训机构推荐;2026权威测评出国雅思辅导机构口碑榜单
  • 日照市英语雅思培训机构推荐:2026权威测评出国雅思辅导机构口碑榜单
  • 基于springboot的应急指挥通信管理系统设计实现
  • 论文查重照片怎么压缩?论文查重照片太大怎么办?
  • 从国家版本馆到企业展厅:凡拓数创的数智展馆进化论
  • 2026年全国高杆灯厂家权威榜单及选型指南 覆盖全场景工程需求 优选解析方案
  • 一番赏盲盒抽卡机小程序:解锁惊喜体验与社交乐趣的多元功能设计
  • 如何利用YashanDB数据库提升数据查询效率
  • 威海市英语雅思培训机构推荐-2026权威测评出国雅思辅导机构口碑榜单
  • logback 速查上手
  • 推荐一个极为好用的数学物理的网站 - Rye
  • 如何利用YashanDB数据库提升企业数据决策效率
  • 威海市英语雅思培训机构推荐:2026权威测评出国雅思辅导机构口碑榜单
  • 旧物回收小程序前端功能设计:以用户为核心构建环保便捷通道
  • 数据库连接池原理:HikariCP为何性能卓越
  • 2026年展厅设计优质企业Top5推荐:数智技术赋能+全维度选择指南
  • 国标GB28181算法算力平台EasyGBS城市广场智慧监控与治理方案设计
  • 如何利用YashanDB数据库提升企业数据运营效率
  • 国内苹果MAC电脑安装Rust开发环境捷径路线
  • 济宁市英语雅思培训机构推荐,2026权威测评出国雅思辅导机构口碑榜单
  • Clawdbot MVP:从 0 → 1 的可落地设计方案