栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

代码示例 ---- spring boot 扫描指定包内接口,自动创建代理类

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

代码示例 ---- spring boot 扫描指定包内接口,自动创建代理类

期望目标
    提供一个可以扫描指定包的注解该包下,全部为接口类型在spring boot环境中,可以正常注入扫描包内的全部接口扫描包内的接口,使用代理模式实现,且,方法执行时,执行自定义代码段
思路解析
    自定义一个注解该注解需要具备一个数组参数,用于存储扫描包的路径已知包内均为接口类型,也就是说,没有实现类,ioc注入必然报错,需要动态创建代理类代理模式两种方案,jdk需要预先实现相关接口,不太方便,cglib可能会更方便一些,所以使用cglib去实现相关功能该代理实现需要被ioc管理
代码实现 pom.xml


    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.5.4
         
    
    com.example
    demo
    0.0.1-SNAPSHOT
    demo
    demo
    
        1.8
    
    
        
            commons-io
            commons-io
            2.2
        
       
        
            org.springframework.boot
            spring-boot-starter-web
        
   
        
            org.projectlombok
            lombok
        
    


    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

设计CGLIB代理拦截器,进行方法拦截
package com.example.demo.bean;

import org.springframework.aop.support.AopUtils;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;


public class MyProxyInterceptor implements MethodInterceptor {

    
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        
        // 获取被代理目标的真实 class
        Class targetClass = obj.getClass();
        boolean aopProxy = AopUtils.isAopProxy(obj);
        if (aopProxy) {
            targetClass = AopUtils.getTargetClass(obj);
        }
        String name = targetClass.getName();
        
        // 参考cglib代理实现命名规范
        String[] split = name.split("\$\$");

        System.out.println("class name =====>" + split[0]);

        System.out.println("method name =====>" + method.getName());
        return null;
    }
}


设计一个代理实现类 MyProxyBean
package com.example.demo.bean;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.cglib.proxy.Enhancer;


public class MyProxyBean implements FactoryBean {

    
    private Class myInterfaceClass;

    
    public MyProxyBean(Class myInterfaceClass) {
        this.myInterfaceClass = myInterfaceClass;
    }

    
    @Override
    public boolean isSingleton() {
        return FactoryBean.super.isSingleton();
    }

    
    @Override
    public T getObject() throws Exception {

        //用于创建代理对象的增强器,可以对目标对象进行扩展
        Enhancer enhancer = new Enhancer();
        //将目标对象设置为父类
        enhancer.setSuperclass(myInterfaceClass);
        //设置目标拦截器
        enhancer.setCallback(new MyProxyInterceptor());
        // 创建代理对象
        return (T)enhancer.create();

    }

    
    @Override
    public Class getObjectType() {
        return myInterfaceClass;
    }
}

自定义路径扫描器 MyProxyScan
package com.example.demo.bean;

import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.type.classreading.metadataReader;

import java.io.IOException;
import java.util.Set;


public class MyProxyScan extends ClassPathBeanDefinitionScanner {

    
    public MyProxyScan(BeanDefinitionRegistry registry) {
        super(registry);
    }


    @Override
    protected Set doScan(String... basePackages) {
        return super.doScan(basePackages);
    }

    
    @Override
    protected boolean isCandidateComponent(metadataReader metadataReader) throws IOException {
        return metadataReader.getClassmetadata().isInterface();
    }

    
    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        return beanDefinition.getmetadata().isInterface();
    }
}

自定义注解解析器 MyProxyBeanimportSelector
package com.example.demo.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.importSelector;
import org.springframework.core.type.Annotationmetadata;
import org.springframework.util.CollectionUtils;

import java.util.Map;
import java.util.Set;


@Configuration
public class MyProxyBeanimportSelector implements importSelector, BeanFactoryAware {

    
    private BeanFactory beanFactory;

    
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }



    
    @Override
    public String[] selectimports(Annotationmetadata importingClassmetadata) {
        // 转换为 DefaultListableBeanFactory 便于操作
        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) beanFactory;

        // 获取自定义注解的具体数据信息
        Map annotationAttributes = importingClassmetadata.getAnnotationAttributes(MyProxy.class.getName());

        if (!CollectionUtils.isEmpty(annotationAttributes)) {
            // 获取配置的扫描包路径
            String[] scanPackages = (String[]) annotationAttributes.get("scanPackages");

            // 自定义扫描器,获取 BeanDefinitionHolder
            MyProxyScan myProxyScan = new MyProxyScan(defaultListableBeanFactory);
            Set beanDefinitionHolders = myProxyScan.doScan(scanPackages);

            // 循环处理每个被扫描到的bean对象,创建代理实现类
            for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {

                // 转换为抽象实现,便于操作具体对象
                AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) beanDefinitionHolder.getBeanDefinition();

                try {

                    // 获取当前被扫描到到接口到具体 class name
                    String beanClassName = beanDefinition.getBeanClassName();
                    // 装载 class
                    Class targetInterface = Class.forName(beanClassName);

                    // 为该自定义的代理实现类,提供构造方法所需要的原始接口类型参数
                    beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(targetInterface);


                    // 修改被扫描接口到具体实现类型,替换为自定义到代理实现类
                    beanDefinition.setBeanClassName(MyProxyBean.class.getName());

                    String beanName = beanDefinitionHolder.getBeanName();
                    System.out.println("已修改===>" + beanName);
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }
        // 故意返回空
        return new String[0];
    }


}

自定义注解 MyProxy
package com.example.demo.bean;

import org.springframework.context.annotation.import;

import java.lang.annotation.*;


@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@documented
@import(MyProxyBeanimportSelector.class)
public @interface MyProxy {

    
    String[] value();
}
在启动器添加自定义注解
package com.example.demo;

import com.example.demo.bean.MyProxy;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@MyProxy(scanPackages = "com.example.demo.post")
@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
        System.out.println("-------------------------------start done-----------------------------------------");
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/712214.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号