【封装】【JS】getClassName方法、get class+id封装

//-------------------封装1 getClassName--------------------------
        //形参传入一个字符串,通过此方法,获取界面中所有含有此类名的DOM元素。
        //并返回包含所有类名DOM的数组
        //因为我们遍历所有的DOM对象很占内存,所以我们可以挑出制定的DOM对象,并从中挑出classname。
        function getClassName(para,obj){
            obj = obj||document;
            if(obj.getElementsByClassName){
                return obj.getElementsByClassName(para);
            } else {
                var boxClass = obj.getElementsByTagName('*');
                var arrClass = [];
                for (var i = 0; i < boxClass.length; i++) {
                    // var name = boxClass[i].className;
                    var nameBox = boxClass[i].className.split(' ');
                    for (var j = 0; j < nameBox.length; j++) {
                        if (nameBox[j] == para) {
                            arrClass.push(boxClass[i]);
                        }
                    };
                };
            }
            return(arrClass);
        }

//封装2 id+class
function
$(para,obj){ if(para.charAt(0) == '#' ){ //通过截取字符串来判断执行的是获取id还是class var arr = para.split("#"); var idName = arr[1]; return document.getElementById(idName); } else if(para.charAt(0) == '.') { var arr1 = para.split("."); var classming = arr1[1]; obj = obj||document; if(obj.getElementsByClassName){ return obj.getElementsByClassName(classming); } else { var boxClass = obj.getElementsByTagName('*'); var arrClass = []; for (var i = 0; i < boxClass.length; i++) { var nameBox = boxClass[i].className.split(' '); for (var j = 0; j < nameBox.length; j++) { if (nameBox[j] == classming) { arrClass.push(boxClass[i]); } }; }; } return(arrClass); } else { return false; } }

 

转载于:https://www.cnblogs.com/LeeHT/p/6243798.html

<think>我们正在讨论Spring框架中处理@Configuration注解类的方法。用户的问题聚焦于如何通过configClass.getBeanMethods()方法获取@Configuration类中的BeanMethod信息。 根据引用[2]和引用[4],我们知道Spring会扫描所有候选的Bean定义,特别是标记为@Configuration的类。在找到这些类后,Spring会解析它们,包括解析其中的@Bean方法。 引用[4]提到:“把类放在configurationClasses。后面再创建bd(loadBeanDefinitions())”,这意味着在解析配置类的过程中,会将这些配置类(ConfigurationClass)对象存储起来,随后会调用loadBeanDefinitions()方法来加载这些配置类中定义的Bean。 用户的问题是如何使用configClass.getBeanMethods()方法获取@Configuration类中的BeanMethod。这里的关键是,我们首先需要获取到代表@Configuration类的ConfigurationClass对象,然后调用其getBeanMethods()方法。 步骤: 1. 首先,我们需要获取到所有的配置类(ConfigurationClass)。这通常是通过Spring的配置类后处理器(如ConfigurationClassPostProcessor)来完成的。 2. 在解析配置类的过程中,Spring会收集配置类中所有被@Bean注解的方法,并将它们封装为BeanMethod对象,存储在ConfigurationClass对象中。 3. 因此,一旦我们有了一个ConfigurationClass对象(代表一个@Configuration注解的类),我们就可以调用其getBeanMethods()方法来获取该配置类中所有@Bean方法对应的BeanMethod对象。 但是,用户可能是在扩展Spring功能时需要获取这些信息,例如在自定义的BeanFactoryPostProcessor或BeanDefinitionRegistryPostProcessor中。 示例代码思路: 我们可以通过实现BeanDefinitionRegistryPostProcessor接口,在postProcessBeanDefinitionRegistry方法中获取到所有已经注册的Bean定义,然后筛选出配置类(即被@Configuration注解的类)的Bean定义。但是注意,此时这些配置类可能还没有被完全解析(因为配置类解析通常也是由ConfigurationClassPostProcessor完成的,它也是一个BeanDefinitionRegistryPostProcessor,且优先级较高)。 因此,为了确保配置类已经被解析,我们需要在ConfigurationClassPostProcessor之后执行。我们可以通过设置自定义后处理器的顺序来实现(例如,设置Ordered.LOWEST_PRECEDENCE)。 然而,在自定义后处理器中,我们可能无法直接获取到ConfigurationClass对象,因为Spring在解析完配置类后,并不会将ConfigurationClass对象保留在BeanFactory中。但是,我们可以通过反射从Spring内部获取这些信息。 另一种方法是,我们可以监听或模拟Spring的配置类解析过程。但这样比较复杂。 实际上,在Spring内部,配置类的解析结果(ConfigurationClass)存储在ConfigurationClassUtils和ConfigurationClassParser中,但这些是内部类,不推荐直接使用。 因此,更合理的方式是:在Spring容器启动后,我们可以通过ApplicationContext获取所有被@Configuration注解的Bean,然后通过反射获取这些类中的@Bean方法。但这并不是通过configClass.getBeanMethods()方法(因为configClass是Spring内部使用的对象)。 如果用户确实需要在Spring内部扩展时使用(比如自己编写一个后处理器,并且想要在配置类解析后获取这些信息),那么可能需要模仿Spring的做法: 在引用[2]中,我们看到Spring在解析配置类时,会检查Bean定义是否是配置类候选者(ConfigurationClassUtils.checkConfigurationClassCandidate)。然后,将候选的配置类放入configCandidates中,随后进行解析。 解析配置类的过程会调用ConfigurationClassParser的parse方法,该方法会解析配置类,包括其@Bean方法。解析完成后,会生成ConfigurationClass对象,其中就包含了该配置类中所有的BeanMethod(通过getBeanMethods()获取)。 但是,这些ConfigurationClass对象存储在ConfigurationClassPostProcessor的configurationClasses属性中(在解析过程中收集的,见引用[4]:this.configurationClasses.put(configClass, configClass);)。然而,这个属性是私有的,我们无法直接访问。 因此,我们可以考虑通过反射来获取ConfigurationClassPostProcessor中的configurationClasses属性。但这样做有风险,因为Spring内部实现可能会变化。 另一种方法是,我们可以自定义一个BeanFactoryPostProcessor,并实现PriorityOrdered接口(保证在ConfigurationClassPostProcessor之后执行,因为ConfigurationClassPostProcessor实现了PriorityOrdered,且其order为Ordered.LOWEST_PRECEDENCE-10,所以我们设置order为Ordered.LOWEST_PRECEDENCE-9即可在其之后执行)。然后,在postProcessBeanFactory方法中,我们可以通过BeanFactory获取到ConfigurationClassPostProcessor的Bean实例,再通过反射获取其configurationClasses属性。 示例代码: 注意:以下代码依赖于Spring内部实现,可能不适用于所有版本(这里以Spring 5.x为例),且不推荐在生产环境中使用,因为内部实现可能变化。 ```java import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.annotation.ConfigurationClassPostProcessor; import org.springframework.core.Ordered; import org.springframework.core.PriorityOrdered; import java.lang.reflect.Field; import java.util.Map; public class MyConfigurationClassInspector implements BeanFactoryPostProcessor, PriorityOrdered { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { // 获取ConfigurationClassPostProcessor的bean String[] postProcessorNames = beanFactory.getBeanNamesForType(ConfigurationClassPostProcessor.class); for (String name : postProcessorNames) { ConfigurationClassPostProcessor processor = beanFactory.getBean(name, ConfigurationClassPostProcessor.class); // 通过反射获取configurationClasses属性 try { Field configurationClassesField = ConfigurationClassPostProcessor.class.getDeclaredField("configurationClasses"); configurationClassesField.setAccessible(true); Map<ConfigurationClass, ConfigurationClass> configurationClasses = (Map<ConfigurationClass, ConfigurationClass>) configurationClassesField.get(processor); // 遍历所有配置类 for (ConfigurationClass configClass : configurationClasses.keySet()) { // 获取该配置类中的所有BeanMethod Set<BeanMethod> beanMethods = configClass.getBeanMethods(); // 处理beanMethods... // 例如:打印每个BeanMethod的方法名 for (BeanMethod beanMethod : beanMethods) { System.out.println("Configuration class: " + configClass.getMetadata().getClassName() + ", Bean method: " + beanMethod.getMetadata().getMethodName()); } } } catch (NoSuchFieldException | IllegalAccessException e) { throw new RuntimeException("Failed to inspect configuration classes", e); } } } @Override public int getOrder() { // 确保在ConfigurationClassPostProcessor之后执行(ConfigurationClassPostProcessor的order为Ordered.LOWEST_PRECEDENCE-10) return Ordered.LOWEST_PRECEDENCE - 9; } } ``` 但是,请注意,上述方法依赖于Spring内部实现,并且使用了反射,因此存在一定的风险。 如果用户只是想在配置类内部获取本类中的@Bean方法,那么可以在配置类中使用反射(不推荐)或者利用Spring的BeanPostProcessor在Bean初始化后获取当前类的方法并过滤出@Bean方法。 然而,用户的问题明确要求使用configClass.getBeanMethods()方法,所以上述方法是直接针对内部ConfigurationClass对象的。 另外,在Spring 5.2之后,可能提供了更友好的扩展点,但需要查阅最新文档。 总结:获取@Configuration类中的BeanMethod信息,可以通过在自定义的BeanFactoryPostProcessor(设置合适的顺序)中,通过反射获取ConfigurationClassPostProcessor内部存储的ConfigurationClass对象,然后调用其getBeanMethods()方法。但请注意,这种方法依赖于Spring内部实现,需谨慎使用。 如果用户有更具体的需求,例如在什么阶段获取这些信息,或者获取后做什么,我们可以提供更具体的建议。</think>### 如何获取@Configuration类中的BeanMethod信息 在Spring框架中,要获取`@Configuration`注解类中通过`getBeanMethods()`返回的`BeanMethod`信息,需理解配置类的解析流程。以下是实现步骤和关键代码: --- #### 1. **获取配置类对象** 首先需要获得代表`@Configuration`类的`ConfigurationClass`对象。这通常在配置类解析阶段完成: ```java // 获取所有候选配置类 List<BeanDefinitionHolder> configCandidates = new ArrayList<>(); for (String beanName : beanFactory.getBeanDefinitionNames()) { BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName); if (ConfigurationClassUtils.isConfigurationCandidate(beanDef)) { configCandidates.add(new BeanDefinitionHolder(beanDef, beanName)); } } ``` --- #### 2. **解析配置类获取BeanMethod** 通过`ConfigurationClassParser`解析配置类,直接调用`configClass.getBeanMethods()`: ```java ConfigurationClassParser parser = new ConfigurationClassParser( metadataReaderFactory, problemReporter, environment, resourceLoader, beanNameGenerator, registry); // 解析配置类 for (BeanDefinitionHolder holder : configCandidates) { BeanDefinition bd = holder.getBeanDefinition(); parser.parse(bd.getBeanClassName()); // 触发解析 } // 获取解析后的ConfigurationClass集合 Set<ConfigurationClass> configClasses = parser.getConfigurationClasses(); // 遍历获取BeanMethod for (ConfigurationClass configClass : configClasses) { Set<BeanMethod> beanMethods = configClass.getBeanMethods(); for (BeanMethod beanMethod : beanMethods) { // 处理BeanMethod信息 MethodMetadata metadata = beanMethod.getMetadata(); String methodName = metadata.getMethodName(); Class<?> returnType = metadata.getReturnType(); // 示例输出:方法名=myBean, 返回类型=com.example.MyBean } } ``` --- #### 关键说明: 1. **`ConfigurationClass`来源** `ConfigurationClass`对象在解析阶段生成并缓存(引用[4]:`this.configurationClasses.put(configClass, configClass)`),通过`ConfigurationClassParser`的解析结果获取[^4]。 2. **`BeanMethod`包含的信息** 每个`BeanMethod`封装了以下元数据(引用[3]): - 方法名称(`methodName`) - 返回类型(`returnType`) - `@Bean`注解属性(如`initMethod`、`destroyMethod`) - 所属配置类的引用[^3] 3. **解析时机** 此操作需在**配置类解析完成后、Bean实例化之前**进行(通常在`BeanFactoryPostProcessor`或`BeanDefinitionRegistryPostProcessor`中实现)。 --- #### 完整流程示例 ```java public class BeanMethodInspector implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { // 1. 创建配置类解析器 ConfigurationClassParser parser = new ConfigurationClassParser(...); // 2. 定位所有@Configuration类 List<BeanDefinitionHolder> configCandidates = findConfigurationClasses(registry); // 3. 解析配置类 parser.parse(configCandidates); // 4. 获取BeanMethod for (ConfigurationClass configClass : parser.getConfigurationClasses()) { Set<BeanMethod> methods = configClass.getBeanMethods(); methods.forEach(method -> System.out.println("BeanMethod: " + method.getMetadata().getMethodName()) ); } } } ``` > **注意**:直接操作`ConfigurationClassParser`属于Spring内部API,建议在扩展框架功能时使用。常规开发中应优先考虑标准Spring API。 --- ### 相关问题 1. 如何在不使用Spring内部API的情况下获取所有`@Bean`方法的信息? 2. `BeanMethod`与`BeanDefinition`有何关联?Spring如何将`@Bean`方法转换为Bean定义? 3. 在配置类解析过程中,`@Bean`方法的依赖注入是如何处理的? 4. 如何自定义`BeanMethod`的处理逻辑(如过滤特定条件的`@Bean`方法)? [^1]: 引用[1] [^3]: 引用[3] [^4]: 引用[4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值