美文网首页
Spring Bean 方法调用

Spring Bean 方法调用

作者: Tinyspot | 来源:发表于2023-12-26 15:58 被阅读0次

1. 工具类

@Component
public class SpringBeanUtils implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringBeanUtils.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public static <T> T getBean(Class<T> clazz) {
        return applicationContext.getBean(clazz);
    }

    public static Object getBean(String name) {
        return applicationContext.getBean(name);
    }

    public static <T> Map<String, T> getBeansOfType(Class<T> clazz) {
        return applicationContext.getBeansOfType(clazz);
    }

    public static List<String> getBeans() {
        String[] beanDefinitionNames = getApplicationContext().getBeanDefinitionNames();
        List<String> beanNames = Arrays.stream(beanDefinitionNames)
                .filter(str -> !str.contains("."))
                .collect(Collectors.toList());
        beanNames.sort(String::compareTo);

        return beanNames;
    }
}

2. 获取 Bean 和方法

@RestController
public class SpringBeansController {

    @RequestMapping("/getBeans")
    public List<String> getBeans() {
        return SpringBeanUtils.getBeans();
        // return JSON.toJSONString(beanNames, SerializerFeature.PrettyFormat);
    }

    @RequestMapping("/getBeanByName")
    public EnvBean getBeanByName(String name) {
        return (EnvBean) SpringBeanUtils.getBean(name);
    }
    
    @RequestMapping("/getBeanByClass")
    public String getBeanByClass() {
        // expected single matching bean but found 2: bizEnvBean,sysEnvBean
        // EnvBean bean = SpringBeanUtils.getBean(EnvBean.class);

        Map<String, EnvBean> beansOfType = SpringBeanUtils.getBeansOfType(EnvBean.class);
        return JSON.toJSONString(beansOfType);
    }

    /**
     * 测试 Bean 名称
     */
    @RequestMapping("/getBeanName")
    public String getBeanName(String name) {
        return Introspector.decapitalize(name);
    }

    @RequestMapping("/getMethods")
    public List<String> getMethods(String beanName) {
        List<String> list = new ArrayList<>();

        Object beanObj = SpringBeanUtils.getBean(beanName);
        Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(beanObj.getClass());
        for (Method method : methods) {
            String methodSign = method.toString();
            list.add(method.getName() + methodSign.substring(methodSign.indexOf("("), methodSign.indexOf(")") + 1));
        }
        return list;
    }
}
@Service
// @Service("greetService")
public class GreetServiceImpl implements GreetService {

    @Override
    public String greeting(UserDTO userDTO, String env) {
        return "greeting:" + userDTO.toString() + "; env=" + env;
    }

    @Override
    public String greet() {
        return "greet...";
    }

    @Override
    public String greet(String name) {
        return "Hello " + name;
    }

}

3. BeanUtils.populate() 方法

 <dependency>
    <groupId>commons-beanutils</groupId>
    <artifactId>commons-beanutils</artifactId>
    <version>1.9.4</version>
</dependency>
/**
 * 方法调用
 */
@RequestMapping("/methodDemo")
public String methodDemo() throws Exception {
    String beanName = "greetServiceImpl";
    String methodName = "greeting(com.example.concrete.common.domain.UserDTO,java.lang.String)";

    Map<String, String> paramMap = new HashMap<>();
    paramMap.put("com.example.concrete.common.domain.UserDTO", "{\"name\":\"Tinyspot\", \"age\":20}");
    paramMap.put("java.lang.String", "dev");

    Object proxyObj = SpringBeanUtils.getBean(beanName);
    Method proxyMethod = ApacheBeanUtils.getMethod(proxyObj.getClass(), methodName);
    List<Object> parameters = ApacheBeanUtils.getMethodParamList(proxyMethod, paramMap);
    Object result = proxyMethod.invoke(proxyObj, parameters.toArray());

    // 等价调用,主要是引用类型的转换
    Object normalInvoke = proxyMethod.invoke(proxyObj, new UserDTO("Tinyspot", 20), "dev");
    System.out.println("normalInvoke: " + normalInvoke);

    return result.toString();
}

工具类

public class ApacheBeanUtils {

    private static final List<Class> PRIMARY_CLASS = Arrays.asList(Integer.class, Boolean.class,
            Double.class, Byte.class, Short.class, Long.class, Float.class, BigDecimal.class, String.class);

    /**
     * @param proxyObject
     * @param methodName 带参数类型的方法名,比如 greet(java.lang.String)
     * @return
     */
    public static Method getMethod(Class<?> proxyObject, String methodName) {
        Method[] methods = proxyObject.getMethods();
        for (Method method : methods) {
            String methodSign = method.toString();
            if (methodSign.contains(methodName)) {
                return method;
            }
        }
        return null;
    }

    /**
     * 获取方法实际参数
     */
    public static List<Object> getMethodParamList(Method method, Map<String, String> paramMap) throws Exception {
        List<Object> objects = new ArrayList<>();

        for (Class<?> parameterType : method.getParameterTypes()) {
            Object obj = null;
            if (PRIMARY_CLASS.contains(parameterType)) {
                obj = paramMap.get(parameterType.getTypeName());
                // obj = ConvertUtils.convert(obj, parameterType);
            } else if (!parameterType.isPrimitive()) {
                obj = getInstance(parameterType);
                String value = paramMap.get(parameterType.getTypeName());
                // org.apache.commons.beanutils.BeanUtils;
                BeanUtils.populate(obj, JSON.parseObject(value));
            }
            objects.add(obj);
        }
        return objects;
    }

    /**
     * 获取类型实例
     * @param parameterType
     * @return
     */
    private static Object getInstance(Class<?> parameterType) throws Exception {
        if (parameterType.isAssignableFrom(List.class)) {
            return new ArrayList<>();
        } else if (parameterType.isAssignableFrom(Map.class)) {
            return new HashMap<>();
        } else if (parameterType.isAssignableFrom(Set.class)) {
            return new HashSet<>();
        }
        return parameterType.newInstance();
    }
}

4. ReflectionUtils 工具类

@RequestMapping("/invokeMethod")
public String invokeMethod() {
    Object beanObj = SpringBeanUtils.getBean("greetServiceImpl");
    // org.springframework.util.ReflectionUtils;

    // 无参方法
    Method greet = ReflectionUtils.findMethod(beanObj.getClass(), "greet");
    Object greetResult = ReflectionUtils.invokeMethod(greet, beanObj);

    // 有参方法
    Method method = ReflectionUtils.findMethod(beanObj.getClass(), "greet", String.class);
    Object result = ReflectionUtils.invokeMethod(method, beanObj, "Tinyspot");

    return greetResult.toString() + result.toString();
}

其他待定

相关文章

  • 各种注解

    @bean 声明为bean对象,并交给Spring管理,产生这个Bean对象的方法Spring只会调用一次,随后这...

  • Spring中Bean的获取分析

    当我们在Spring中获取bean时,会调用applicationContext.getBean("")方法,我们...

  • 8、Spring-XML-生命周期

    一、概要 Spring容器负责管理Bean的生命周期 创建bean实例 设置bean的属性值 调用初始化回调方法 ...

  • Spring-XML的生命周期

    一、概要 Spring容器负责管理Bean的生命周期 创建bean实例 设置bean的属性值 调用初始化回调方法 ...

  • Spring事务

    Spring有7种传播机制 事务传播机制只适用于不同的bean之间方法的调用,如果一个bean中的两个方法相互调用...

  • spring 容器启动完成后进行某些操作

    两种方法: @PostConstruct spring 初始化bean之后会调用。 实现ApplicationLI...

  • Spring源码分析-----加载bean

    先看下简单的Spring应用 获取bean的时候调用getBean方法,跟踪源码发现最后调用的是doGetBean...

  • SpEL

    Spring表达式语言(SpEL),它的特性包括: 使用bean的ID来引用bean. 调用方法和访问对象的属性。...

  • 关于spring,总结了一篇上万字的图文笔记,不管你工作几年都应

    spring bean的实例化 构造器实例化 静态工厂实例化 容器创建对象,不直接调用对象构造方法,而是调用静态工...

  • Spring常用注解

    spring开发中常用到的注解 @PostConstruct在bean初始化之后调用方法,可以用@PostCons...

网友评论

      本文标题:Spring Bean 方法调用

      本文链接:https://www.haomeiwen.com/subject/ctvlndtx.html