Rumah  >  Artikel  >  Java  >  Bagaimana untuk membangunkan pemalam Springboot

Bagaimana untuk membangunkan pemalam Springboot

王林
王林ke hadapan
2023-05-16 09:31:051261semak imbas

    Latar Belakang

    Projek ini menambah sistem pemantauan untuk memantau panggilan antara muka setiap sistem Pada peringkat awal, ia berdasarkan pakej pergantungan yang biasa dirujuk oleh setiap projek. Aspek AOP ditambahkan untuk memantau panggilan antara muka setiap sistem, tetapi ini mempunyai kelemahan Pertama, laluan antara muka projek yang berbeza, menyebabkan laluan berbilang aspek ditulis untuk aspek AOP. sesetengah sistem tidak perlu dipantau Kerana pakej awam diperkenalkan dan dipantau, ia terlalu mengganggu. Untuk menyelesaikan masalah ini, anda boleh menggunakan atribut boleh pasang springboot.

    Pembangunan pemalam log pemantauan kedua

    1 Cipta kelas pelaksanaan aspek aop baharu MonitorLogInterceptor

    @Slf4j
    public class MonitorLogInterceptor extends MidExpandSpringMethodInterceptor<MonitorAspectAdviceProperties> {
       @Override
       public Object invoke(MethodInvocation methodInvocation) throws Throwable {
           Object result = null;
           HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
           //拿到请求的url
           String requestURI = request.getRequestURI();
           if (StringUtils.isEmpty(requestURI)) {
               return result;
           }
           try {
               result = methodInvocation.proceed();
           } catch (Exception e) {
               buildRecordData(methodInvocation, result, requestURI, e);
               throw e;
           }
           //参数数组
           buildRecordData(methodInvocation, result, requestURI, null);
           return result;

    Kita dapat melihat bahawa ia melaksanakanMidExpandSpringMethodInterceptor8742468051c85b06f0a0af9e3e506b5c

    @Slf4j
    public abstract class MidExpandSpringMethodInterceptor<T> implements MethodInterceptor {
        @Setter
        @Getter
        protected T properties;
        /**
         * 主动注册,生成AOP工厂类定义对象
         */
        protected String getExpression() {
            return null;
        }
        @SuppressWarnings({"unchecked"})
        public AbstractBeanDefinition doInitiativeRegister(Properties properties) {
            String expression = StringUtils.isNotBlank(this.getExpression()) ? this.getExpression() : properties.getProperty("expression");
            if (StringUtils.isBlank(expression)) {
                log.warn("中台SpringAop插件 " + this.getClass().getSimpleName() + " 缺少对应的配置文件 或者 是配置的拦截路径为空 导致初始化跳过");
                return null;
            }
            BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(AspectJExpressionPointcutAdvisor.class);
            this.setProperties((T) JsonUtil.toBean(JsonUtil.toJson(properties), getProxyClassT()));
            definition.addPropertyValue("advice", this);
            definition.addPropertyValue("expression", expression);
            return definition.getBeanDefinition();
        }
        /**
         * 获取代理类上的泛型T
         * 单泛型 不支持多泛型嵌套
         */
        private Class<?> getProxyClassT() {
            Type genericSuperclass = this.getClass().getGenericSuperclass();
            ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
            return (Class<?>) parameterizedType.getActualTypeArguments()[0];
        }
    }

    Dan akhirnya Ia melaksanakan MethodInterceptor Antara muka ini ialah pemintas kaedah dan digunakan untuk proksi dinamik dalam pengaturcaraan Spring AOP. Melaksanakan antara muka ini boleh meningkatkan kaedah yang perlu dipertingkatkan tidak Menambah sebarang kaedah seperti @Component dan @Service untuk menyuntik kelas ke dalam kacang spring. Dalam direktori fail, tambahkan fail spring.factories dengan kandungan:

    com.dst.mid.common.expand.springaop.MidExpandSpringMethodInterceptor=

    com.dst.mid.monitor.intercept .MonitorLogInterceptor

    Dengan cara ini, ia boleh didaftarkan terus semasa proses permulaan dan diletakkan di dalam bekas spring. Soalan lain ialah, kini kelas pelaksanaan aspek tersedia, di manakah aspeknya?

    @Configuration
    @Slf4j
    @Import(MidExpandSpringAopAutoStarter.class)
    public class MidExpandSpringAopAutoStarter implements ImportBeanDefinitionRegistrar {
        private static final String BEAN_NAME_FORMAT = "%s%sAdvisor";
        private static final String OS = "os.name";
        private static final String WINDOWS = "WINDOWS";
        @SneakyThrows
        @SuppressWarnings({"rawtypes"})
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            // 1 获取MidExpandSpringMethodInterceptor类的所有实现集合
            List<MidExpandSpringMethodInterceptor> list = SpringFactoriesLoader.loadFactories(MidExpandSpringMethodInterceptor.class, null);
            if (!CollectionUtils.isEmpty(list)) {
                String expandPath;
                Properties properties;
                BeanDefinition beanDefinition;
                // 2 遍历类的所有实现集合
                for (MidExpandSpringMethodInterceptor item : list) {
                    // 3 获取资源文件名称 资源文件中存储需要加入配置的
                    expandPath = getExpandPath(item.getClass());
                    // 4 加载资源文件
                    properties = PropertiesLoaderUtils.loadAllProperties(expandPath + ".properties");
                    // 5 赋值beanDefinition为AspectJExpressionPointcutAdvisor
    
                    if (Objects.nonNull(beanDefinition = item.doInitiativeRegister(properties))) {
                        // 6 向容器中注册类  注意这个beanname是不存在的,但是他赋值beanDefinition为AspectJExpressionPointcutAdvisor是动态代理动态生成代理类所以不会报错
                        registry.registerBeanDefinition(String.format(BEAN_NAME_FORMAT, expandPath, item.getClass().getSimpleName()), beanDefinition);
                    }
                }
            }
        }
        /**
         * 获取资源文件名称
         */
        private static String getExpandPath(Class<?> clazz) {
            String[] split = clazz.getProtectionDomain().getCodeSource().getLocation().getPath().split("/");
            if (System.getProperty(OS).toUpperCase().contains(WINDOWS)) {
                return split[split.length - 3];
            } else {
                return String.join("-", Arrays.asList(split[split.length - 1].split("-")).subList(0, 4));
            }
        }
    }

    Ini adalah pemprosesan kelas pendaftaran aspek Pertama,
    dilaksanakan dengan kaedah

    nya, anda boleh meletakkan kelas yang anda ingin daftarkan ke dalam bekas spring pada pelaksanaannya

    ImportBeanDefinitionRegistrarregisterBeanDefinitions1 Dapatkan semua koleksi pelaksanaan kelas MidExpandSpringMethodInterceptor

    • 2 Lintas semua koleksi pelaksanaan kelas

    • 3 Dapatkan nama fail Sumber Fail sumber menyimpan

    • 4 yang perlu ditambahkan pada konfigurasi 4. Muatkan fail sumber

    • 5. proksi yang menjana kelas proksi secara dinamik, jadi tiada ralat akan dilaporkan

    • Lihat Pada ketika ini, masih terdapat masalah

      Ia sebenarnya untuk mendaftarkan kelas ke dalam bekas, tetapi satu langkah lagi ialah ia perlu diimbas oleh bekas Kaedah sebelumnya adalah untuk mengimbas melalui laluan dalam projek, tetapi kami adalah pemalam dan tidak boleh Bergantung pada projek, tetapi mengendalikannya dengan cara anda sendiri kali ini, anda perlu menggunakan
    • untuk mengendalikannya.
    • Melalui pemprosesan di atas, pemprosesan plug-in pemantauan direalisasikan Kemudian apabila menggunakannya, anda hanya perlu memperkenalkan projek ini kepada projek yang berbeza yang perlu dipantau.

    Atas ialah kandungan terperinci Bagaimana untuk membangunkan pemalam Springboot. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

    Kenyataan:
    Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam