优秀的编程知识分享平台

网站首页 > 技术文章 正文

Spring Boot 神奇的2个类!动态方法查找调用

nanyue 2025-05-27 16:36:48 技术文章 7 ℃

1. 环境准备

首先,准备一个Service Bean,该类会在接下来的代码中都会使用到。

@Component("ps")
public class PersonService {
  public void save() {
    System.out.println("PersonService save method invoke...") ;
  }
  public void query(Integer id) {
    System.out.printf("PersonService query method id: %d%n", id) ;
  }
}

该类非常的简单就是为了接下来的演示足够简单清晰。

2. 方法定位

public class MethodLocatingFactoryBean implementsFactoryBean<Method>, BeanFactoryAware {
  private String targetBeanName;
  private String methodName;
  private Method method;
  public Method getObject()throws Exception {
    returnthis.method;
  }
  public Class<Method> getObjectType(){
    return Method.class;
  }
  // ...
}

该类是个FactoryBean,具体返回的是Method对象;该类主要的作用就是通过beanName查找到对应的Class,然后通过设置的methodName查找该Class对应的Method对象。

定义Bean对象

@Configuration
public class AppConfig {
  @Bean
  MethodLocatingFactoryBean methodLocatingFactoryBean() {
    MethodLocatingFactoryBean fb = new MethodLocatingFactoryBean() ;
    // 设置要查找的方法签名
    fb.setMethodName("save") ;
    // 设置beanName
    fb.setTargetBeanName("ps") ;
    return fb ;
  }
}

知道了MethodLocatingFactoryBean返回的是Method,那接下来就可以在其它的Bean中直接注入该Method对象。

@Component
public class BeanMethod {
  // 注入Method
  @Resource
  private Method method ;
  @Resource
  private PersonService target ;
  public Object invoke(Object ... params) throws Exception {
    return method.invoke(target, params) ;
  }
}

测试&输出结果

@Resource
private BeanMethod bm ;
@Test
public void testSave() {
  bm.invoke() ;
}
// 输出
PersonService save method invoke...

配置带参数的方法

MethodLocatingFactoryBean fb = new MethodLocatingFactoryBean() ;
fb.setMethodName("query(java.lang.Integer)") ;

方法的参数类型需要完整的限定名(包名+类名),如果方法参数是基本数据类型,那么直接写基本类型即可(query(int))。

3. 方法调用

public class MethodInvokingFactoryBean extends MethodInvokingBean 
  implements FactoryBean<Object> 
  // 返回的实际对象
  private Object singletonObject
  public void afterPropertiesSet() throws Exception {
    // 准备初始化
    prepare() ;
    if (this.singleton) {
      this.initialized = true;
      // 创建调用;在方法内部会调用设置的目标方法,获取方法的返回值
      this.singletonObject = invokeWithTargetException();
    }
  }
  public Object getObject() throws Exception {
    if (this.singleton) {
      // ...
      return this.singletonObject;
    }
  }
}

该类在初始化方法调用时,会调用目标类的方法,方法返回值作为这里getObject方法的返回对象。

定义一个工厂类(无所谓是否是工厂类)

public class PersonFactory {
  public PersonService getInstance() {
    return new PersonService() ;
  }


  public static PersonService getPs() {
    return new PersonService() ;
  }
}

该类不用注册为Bean对象。接下来配置bean对象

@Configuration
public class AppConfig {
  @Bean
  MethodInvokingFactoryBean methodInvokingFactoryBean() {
    MethodInvokingFactoryBean fb = new MethodInvokingFactoryBean() ;
    // 静态方法
    fb.setTargetClass(PersonFactory.class) ;
    fb.setTargetMethod("getPs") ;
    return fb ;
  }
}

测试&输出结果

@Resource
private PersonService ps ;
@Test
publicvoidtestSave(){
  ps.query(10) ;
}
// 输出
PersonService query method id: 10

配置为非静态方法

MethodInvokingFactoryBean fb = new MethodInvokingFactoryBean() ;
// 非静态方法
fb.setTargetObject(new PersonFactory()) ;
fb.setTargetMethod("getInstance") ;
最近发表
标签列表