spring 通过反射调用service方法

首先介绍一下一下spring ReflectionUtils方法

org.springframework.util.ReflectionUtils 是spring提供的反射工具类,使用它有以下好处:

  • 我们在使用Java反射的时候,需要处理大量的IllegalAccessException,而这个异常,我们在业务逻辑当中,绝大多数情况都不需要捕获,使用Spring工具类,可以直接将其转换为RuntimeException,在业务中无需直接捕获。
  • 使用Spring提供的接口,可以减少很多对Java类的字段方法操作带来的冗余,代码清晰简洁。

以下是 ReflectionUtils 源代码,不需要我们手写,直接在Spring框架中调用即可。

仅供参考:

public abstract class ReflectionUtils {

 //根据类和属性名称查找属性字段
//Attempt to find a {@link Field field} on the supplied {@link Class} with
//the supplied name. Searches all superclasses up to {@link Object}.
//@param clazz the class to introspect
//@param name the name of the field
//@return the corresponding Field object, or null if not found
//
 public static Field findField(Class clazz, String name) {
  return findField(clazz, name, null);
 }

 //根据类和属性名称查找属性字段
//Attempt to find a {@link Field field} on the supplied {@link Class} with
//the supplied name and/or {@link Class type}. Searches all
//superclasses up to {@link Object}.
//@param clazz the class to introspect
// @param name the name of the field (may be null if type is specified)
//@param type the type of the field (may be null if name is specified)
// @return the corresponding Field object, or null if not found
//
 public static Field findField(Class clazz, String name, Class type) {
  Assert.notNull(clazz, "Class must not be null");
  Assert.isTrue(name != null || type != null, "Either name or type of the field must be specified");
  Class searchType = clazz;
  while (!Object.class.equals(searchType) && searchType != null) {
   Field[] fields = searchType.getDeclaredFields();
   for (int i = 0; i < fields.length; i++) {
    Field field = fields[i];
    if ((name == null || name.equals(field.getName()))
      && (type == null || type.equals(field.getType()))) {
     return field;
    }
   }
   searchType = searchType.getSuperclass();
  }
  return null;
 }

 //根据属性字段和对象,设置对象的值
// Set the field represented by the supplied {@link Field field object} on
//the specified {@link Object target object} to the specified
//value. In accordance with
// {@link Field#set(Object, Object)} semantics, the new value is
// automatically unwrapped if the underlying field has a primitive type.
// 

Thrown exceptions are handled via a call to // {@link #handleReflectionException(Exception)}. // @param field the field to set // @param target the target object on which to set the field // @param value the value to set; may be null // public static void setField(Field field, Object target, Object value) { try { field.set(target, value); } catch (IllegalAccessException ex) { handleReflectionException(ex); throw new IllegalStateException( "Unexpected reflection exception - " + ex.getClass().getName() + ": " + ex.getMessage()); } } //根据属性字段和对象,获取的对象中字段的值 // Get the field represented by the supplied {@link Field field object} on // the specified {@link Object target object}. In accordance with // {@link Field#get(Object)} semantics, the returned value is // automatically wrapped if the underlying field has a primitive type. //

Thrown exceptions are handled via a call to // {@link #handleReflectionException(Exception)}. // @param field the field to get // @param target the target object from which to get the field // @return the field's current value public static Object getField(Field field, Object target) { try { return field.get(target); } catch (IllegalAccessException ex) { handleReflectionException(ex); throw new IllegalStateException( "Unexpected reflection exception - " + ex.getClass().getName() + ": " + ex.getMessage()); } } //根据类,方法名称和参数类型查找方法 // Attempt to find a {@link Method} on the supplied class with the supplied name // and no parameters. Searches all superclasses up to Object. //

Returns null if no {@link Method} can be found. // @param clazz the class to introspect // @param name the name of the method // @return the Method object, or null if none found public static Method findMethod(Class clazz, String name) { return findMethod(clazz, name, new Class[0]); } //根据类,方法名称和参数类型查找方法 // Attempt to find a {@link Method} on the supplied class with the supplied name // and parameter types. Searches all superclasses up to Object. //

Returns null if no {@link Method} can be found. // @param clazz the class to introspect // @param name the name of the method // @param paramTypes the parameter types of the method // (may be null to indicate any signature) // @return the Method object, or null if none found public static Method findMethod(Class clazz, String name, Class[] paramTypes) { Assert.notNull(clazz, "Class must not be null"); Assert.notNull(name, "Method name must not be null"); Class searchType = clazz; while (!Object.class.equals(searchType) && searchType != null) { Method[] methods = (searchType.isInterface() ? searchType.getMethods() : searchType.getDeclaredMethods()); for (int i = 0; i < methods.length; i++) { Method method = methods[i]; if (name.equals(method.getName()) && (paramTypes == null || Arrays.equals(paramTypes, method.getParameterTypes()))) { return method; } } searchType = searchType.getSuperclass(); } return null; } //调用方法的应用 // Invoke the specified {@link Method} against the supplied target object // with no arguments. The target object can be null when // invoking a static {@link Method}. //

Thrown exceptions are handled via a call to {@link #handleReflectionException}. // @param method the method to invoke // @param target the target object to invoke the method on // @return the invocation result, if any // @see #invokeMethod(java.lang.reflect.Method, Object, Object[]) public static Object invokeMethod(Method method, Object target) { return invokeMethod(method, target, null); } //调用方法的应用 // Invoke the specified {@link Method} against the supplied target object // with the supplied arguments. The target object can be null // when invoking a static {@link Method}. //

Thrown exceptions are handled via a call to {@link #handleReflectionException}. // @param method the method to invoke // @param target the target object to invoke the method on // @param args the invocation arguments (may be null) // @return the invocation result, if any public static Object invokeMethod(Method method, Object target, Object[] args) { try { return method.invoke(target, args); } catch (Exception ex) { handleReflectionException(ex); } throw new IllegalStateException("Should never get here"); } // Invoke the specified JDBC API {@link Method} against the supplied // target object with no arguments. // @param method the method to invoke // @param target the target object to invoke the method on // @return the invocation result, if any // @throws SQLException the JDBC API SQLException to rethrow (if any) // @see #invokeJdbcMethod(java.lang.reflect.Method, Object, Object[]) public static Object invokeJdbcMethod(Method method, Object target) throws SQLException { return invokeJdbcMethod(method, target, null); } // Invoke the specified JDBC API {@link Method} against the supplied // target object with the supplied arguments. // @param method the method to invoke // @param target the target object to invoke the method on // @param args the invocation arguments (may be null) // @return the invocation result, if any // @throws SQLException the JDBC API SQLException to rethrow (if any) // @see #invokeMethod(java.lang.reflect.Method, Object, Object[]) public static Object invokeJdbcMethod(Method method, Object target, Object[] args) throws SQLException { try { return method.invoke(target, args); } catch (IllegalAccessException ex) { handleReflectionException(ex); } catch (InvocationTargetException ex) { if (ex.getTargetException() instanceof SQLException) { throw (SQLException) ex.getTargetException(); } handleInvocationTargetException(ex); } throw new IllegalStateException("Should never get here"); } //处理异常的方法//使用反射处理异常的将异常信息输出但不抛出方法以外 // Handle the given reflection exception. Should only be called if // no checked exception is expected to be thrown by the target method. //

Throws the underlying RuntimeException or Error in case of an // InvocationTargetException with such a root cause. Throws an // IllegalStateException with an appropriate message else. // @param ex the reflection exception to handle public static void handleReflectionException(Exception ex) { if (ex instanceof NoSuchMethodException) { throw new IllegalStateException("Method not found: " + ex.getMessage()); } if (ex instanceof IllegalAccessException) { throw new IllegalStateException("Could not access method: " + ex.getMessage()); } if (ex instanceof InvocationTargetException) { handleInvocationTargetException((InvocationTargetException) ex); } if (ex instanceof RuntimeException) { throw (RuntimeException) ex; } handleUnexpectedException(ex); } //Handle the given invocation target exception. Should only be called if //no checked exception is expected to be thrown by the target method. //

Throws the underlying RuntimeException or Error in case of such // a root cause. Throws an IllegalStateException else. // @param ex the invocation target exception to handle public static void handleInvocationTargetException(InvocationTargetException ex) { rethrowRuntimeException(ex.getTargetException()); } //Rethrow the given {@link Throwable exception}, which is presumably the //target exception of an {@link InvocationTargetException}. //Should only be called if no checked exception is expected to be thrown by //the target method. //

Rethrows the underlying exception cast to an {@link RuntimeException} //or {@link Error} if appropriate; otherwise, throws an //{@link IllegalStateException}. // @param ex the exception to rethrow // @throws RuntimeException the rethrown exception public static void rethrowRuntimeException(Throwable ex) { if (ex instanceof RuntimeException) { throw (RuntimeException) ex; } if (ex instanceof Error) { throw (Error) ex; } handleUnexpectedException(ex); } //Rethrow the given {@link Throwable exception}, which is presumably the //target exception of an {@link InvocationTargetException}. //Should only be called if no checked exception is expected to be thrown by //the target method. //

Rethrows the underlying exception cast to an {@link Exception} or //{@link Error} if appropriate; otherwise, throws an //{@link IllegalStateException}. // @param ex the exception to rethrow // @throws Exception the rethrown exception (in case of a checked exception) public static void rethrowException(Throwable ex) throws Exception { if (ex instanceof Exception) { throw (Exception) ex; } if (ex instanceof Error) { throw (Error) ex; } handleUnexpectedException(ex); } //Throws an IllegalStateException with the given exception as root cause. //@param ex the unexpected exception private static void handleUnexpectedException(Throwable ex) { // Needs to avoid the chained constructor for JDK 1.4 compatibility. IllegalStateException isex = new IllegalStateException("Unexpected exception thrown"); isex.initCause(ex); throw isex; } //Determine whether the given method explicitly declares the given exception // or one of its superclasses, which means that an exception of that type //can be propagated as-is within a reflective invocation. //@param method the declaring method //@param exceptionType the exception to throw //@return true if the exception can be thrown as-is; //false if it needs to be wrapped public static boolean declaresException(Method method, Class exceptionType) { Assert.notNull(method, "Method must not be null"); Class[] declaredExceptions = method.getExceptionTypes(); for (int i = 0; i < declaredExceptions.length; i++) { Class declaredException = declaredExceptions[i]; if (declaredException.isAssignableFrom(exceptionType)) { return true; } } return false; } //判断方法,属性字段等的修饰符的方法 //Determine whether the given field is a "public static final" constant. // @param field the field to check public static boolean isPublicStaticFinal(Field field) { int modifiers = field.getModifiers(); return (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)); } //Determine whether the given method is an "equals" method. //@see java.lang.Object#equals public static boolean isEqualsMethod(Method method) { if (method == null || !method.getName().equals("equals")) { return false; } Class[] paramTypes = method.getParameterTypes(); return (paramTypes.length == 1 && paramTypes[0] == Object.class); } //Determine whether the given method is a "hashCode" method. //@see java.lang.Object#hashCode public static boolean isHashCodeMethod(Method method) { return (method != null && method.getName().equals("hashCode") && method.getParameterTypes().length == 0); } // Determine whether the given method is a "toString" method. //@see java.lang.Object#toString() public static boolean isToStringMethod(Method method) { return (method != null && method.getName().equals("toString") && method.getParameterTypes().length == 0); } //判断一个属性是否可以访问的方法 //Make the given field accessible, explicitly setting it accessible if necessary. //The setAccessible(true) method is only called when actually necessary, //to avoid unnecessary conflicts with a JVM SecurityManager (if active). //@param field the field to make accessible //@see java.lang.reflect.Field#setAccessible public static void makeAccessible(Field field) { if (!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())) { field.setAccessible(true); } } //判断一个方法是否可以访问的方法 //Make the given method accessible, explicitly setting it accessible if necessary. //The setAccessible(true) method is only called when actually necessary, //to avoid unnecessary conflicts with a JVM SecurityManager (if active). //@param method the method to make accessible //@see java.lang.reflect.Method#setAccessible public static void makeAccessible(Method method) { if (!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) { method.setAccessible(true); } } //判断一个构造函数是否可以访问的方法 //Make the given constructor accessible, explicitly setting it accessible if necessary. //The setAccessible(true) method is only called when actually necessary, //to avoid unnecessary conflicts with a JVM SecurityManager (if active). //@param ctor the constructor to make accessible //@see java.lang.reflect.Constructor#setAccessible public static void makeAccessible(Constructor ctor) { if (!Modifier.isPublic(ctor.getModifiers()) || !Modifier.isPublic(ctor.getDeclaringClass().getModifiers())) { ctor.setAccessible(true); } } // Perform the given callback operation on all matching methods of the // given class and superclasses. //

The same named method occurring on subclass and superclass will // appear twice, unless excluded by a {@link MethodFilter}. // @param targetClass class to start looking at // @param mc the callback to invoke for each method // @see #doWithMethods(Class, MethodCallback, MethodFilter) public static void doWithMethods(Class targetClass, MethodCallback mc) throws IllegalArgumentException { doWithMethods(targetClass, mc, null); } //Perform the given callback operation on all matching methods of the //given class and superclasses. //

The same named method occurring on subclass and superclass will //appear twice, unless excluded by the specified {@link MethodFilter}. //@param targetClass class to start looking at // @param mc the callback to invoke for each method //@param mf the filter that determines the methods to apply the callback to public static void doWithMethods(Class targetClass, MethodCallback mc, MethodFilter mf) throws IllegalArgumentException { // Keep backing up the inheritance hierarchy. do { Method[] methods = targetClass.getDeclaredMethods(); for (int i = 0; i < methods.length; i++) { if (mf != null && !mf.matches(methods[i])) { continue; } try { mc.doWith(methods[i]); } catch (IllegalAccessException ex) { throw new IllegalStateException( "Shouldn't be illegal to access method '" + methods[i].getName() + "': " + ex); } } targetClass = targetClass.getSuperclass(); } while (targetClass != null); } //获取类的所有的方法的 //Get all declared methods on the leaf class and all superclasses. //Leaf class methods are included first. public static Method[] getAllDeclaredMethods(Class leafClass) throws IllegalArgumentException { final List list = new ArrayList(32); doWithMethods(leafClass, new MethodCallback() { public void doWith(Method method) { list.add(method); } }); return (Method[]) list.toArray(new Method[list.size()]); } //调用字段时执行的回调的方法 //Invoke the given callback on all fields in the target class, //going up the class hierarchy to get all declared fields. //@param targetClass the target class to analyze //@param fc the callback to invoke for each field public static void doWithFields(Class targetClass, FieldCallback fc) throws IllegalArgumentException { doWithFields(targetClass, fc, null); } //调用字段时执行的回调的并过滤的方法 //Invoke the given callback on all fields in the target class, //going up the class hierarchy to get all declared fields. //@param targetClass the target class to analyze //@param fc the callback to invoke for each field //@param ff the filter that determines the fields to apply the callback to public static void doWithFields(Class targetClass, FieldCallback fc, FieldFilter ff) throws IllegalArgumentException { // Keep backing up the inheritance hierarchy. do { // Copy each field declared on this class unless it's static or file. Field[] fields = targetClass.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { // Skip static and final fields. if (ff != null && !ff.matches(fields[i])) { continue; } try { fc.doWith(fields[i]); } catch (IllegalAccessException ex) { throw new IllegalStateException( "Shouldn't be illegal to access field '" + fields[i].getName() + "': " + ex); } } targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); } //用于对象的拷贝的方法(类必须是同一类或子类) //Given the source object and the destination, which must be the same class //or a subclass, copy all fields, including inherited fields. Designed to //work on objects with public no-arg constructors. //@throws IllegalArgumentException if the arguments are incompatible public static void shallowCopyFieldState(final Object src, final Object dest) throws IllegalArgumentException { if (src == null) { throw new IllegalArgumentException("Source for field copy cannot be null"); } if (dest == null) { throw new IllegalArgumentException("Destination for field copy cannot be null"); } if (!src.getClass().isAssignableFrom(dest.getClass())) { throw new IllegalArgumentException("Destination class [" + dest.getClass().getName() + "] must be same or subclass as source class [" + src.getClass().getName() + "]"); } doWithFields(src.getClass(), new FieldCallback() { public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException { makeAccessible(field); Object srcValue = field.get(src); field.set(dest, srcValue); } }, COPYABLE_FIELDS); } //Action to take on each method. public static interface MethodCallback { //Perform an operation using the given method. //@param method the method to operate on void doWith(Method method) throws IllegalArgumentException, IllegalAccessException; } //Callback optionally used to method fields to be operated on by a method callback. public static interface MethodFilter { //Determine whether the given method matches. //@param method the method to check boolean matches(Method method); } //Callback interface invoked on each field in the hierarchy. public static interface FieldCallback { //Perform an operation using the given field. //@param field the field to operate on void doWith(Field field) throws IllegalArgumentException, IllegalAccessException; } //Callback optionally used to filter fields to be operated on by a field callback. public static interface FieldFilter { //Determine whether the given field matches. //@param field the field to check boolean matches(Field field); } //Pre-built FieldFilter that matches all non-static, non-final fields. public static FieldFilter COPYABLE_FIELDS = new FieldFilter() { public boolean matches(Field field) { return !(Modifier.isStatic(field.getModifiers()) || Modifier.isFinal(field.getModifiers())); } }; }


使用方法如下:

package cn.anycall.wx.service.impl;

import java.lang.reflect.Method;

import javax.transaction.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ReflectionUtils;

import cn.anycall.wx.dao.BaseDao;
import cn.anycall.wx.dao.ProcDao;
import cn.anycall.wx.kit.SpringContextsUtil;
import cn.anycall.wx.service.TestSerivce;
@Service("testService")
@Transactional
public class TestSerivceImpl implements TestSerivce {

    @Autowired
    private BaseDao baseDao;
    @Autowired
    private ProcDao procDao;

    public String testLock(String mob) throws Exception  {

                Method  mh = ReflectionUtils.findMethod(SpringContextsUtil.getBean("testService").getClass(), "testRelect",new Class[]{String.class} );
                Object obj = ReflectionUtils.invokeMethod(mh,  SpringContextsUtil.getBean("testService"),"13761036955");
                System.out.println("obj="+obj);
                baseDao.updateSQL("insert into test_liu(a,b) values(1,2,2)");
        return mob;
    }
    /**
     * 测试反射
     * @param eee
     * @return
     * @throws Exception
     * @throws Exception
     * @throws Exception
     */
    public String testRelect(String eee) throws Exception{
                baseDao.updateSQL("insert into test_liu(a,b) values(2,2)");
        return "111";
    }
}

其中用到 SpringContextsUtil 方法,这个是需要我们手写的;也有使用 SpringContextHolder 的,效果是一样的


import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
 
/**
 * 获取spring容器,以访问容器中定义的其他bean
 *   lyltiger
 *  MOSTsView 3.0 2009-11-16
 */
public class SpringContextUtil implements ApplicationContextAware{
 
    private static ApplicationContext   applicationContext;
 
    /**
     * 实现ApplicationContextAware接口的回调方法,设置上下文环境
     */
    public void setApplicationContext(ApplicationContext applicationContext){
        SpringContextUtil.applicationContext = applicationContext;
    }
 
    public static ApplicationContext getApplicationContext(){
        return applicationContext;
    }
 
    /**
     * 获取对象
     * @return  Object 一个以所给名字注册的bean的实例 (service注解方式,自动生成以首字母小写的类名为bean name)
     */
    public static Object getBean(String name) throws BeansException{
        return applicationContext.getBean(name);
    }
}

在配置文件中加入:

      
      


你可能感兴趣的:(Spring,FrameWork)