mybatis源码-反射封装

  作者:记性不好的阁主

实现关系:






先定义一个调用接口Invoker:


/**
* Copyright 2009-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.reflection.invoker;

import java.lang.reflect.InvocationTargetException;

/**
* @author Clinton Begin
*/
public interface Invoker {
Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException;

Class<?> getType();
}



方法调用类:


/**
* Copyright 2009-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.reflection.invoker;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.apache.ibatis.reflection.Reflector;

/**
* @author Clinton Begin
*/
public class MethodInvoker implements Invoker {

private final Class<?> type;
private final Method method;

public MethodInvoker(Method method) {
this.method = method;

if (method.getParameterTypes().length == 1) {
type = method.getParameterTypes()[0];
} else {
type = method.getReturnType();
}
}

@Override
public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
try {
return method.invoke(target, args);
} catch (IllegalAccessException e) {
if (Reflector.canControlMemberAccessible()) {
method.setAccessible(true);
return method.invoke(target, args);
} else {
throw e;
}
}
}

@Override
public Class<?> getType() {
return type;
}
}


获取类属性调用类:


/**
* Copyright 2009-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.reflection.invoker;

import java.lang.reflect.Field;

import org.apache.ibatis.reflection.Reflector;

/**
* @author Clinton Begin
*/
public class GetFieldInvoker implements Invoker {
private final Field field;

public GetFieldInvoker(Field field) {
this.field = field;
}

@Override
public Object invoke(Object target, Object[] args) throws IllegalAccessException {
try {
return field.get(target);
} catch (IllegalAccessException e) {
if (Reflector.canControlMemberAccessible()) {
field.setAccessible(true);
return field.get(target);
} else {
throw e;
}
}
}

@Override
public Class<?> getType() {
return field.getType();
}
}


设置类属性调用类:


/**
* Copyright 2009-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.reflection.invoker;

import java.lang.reflect.Field;

import org.apache.ibatis.reflection.Reflector;

/**
* @author Clinton Begin
*/
public class SetFieldInvoker implements Invoker {
private final Field field;

public SetFieldInvoker(Field field) {
this.field = field;
}

@Override
public Object invoke(Object target, Object[] args) throws IllegalAccessException {
try {
field.set(target, args[0]);
} catch (IllegalAccessException e) {
if (Reflector.canControlMemberAccessible()) {
field.setAccessible(true);
field.set(target, args[0]);
} else {
throw e;
}
}
return null;
}

@Override
public Class<?> getType() {
return field.getType();
}
}


异常调用类:


/**
* Copyright 2009-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.ibatis.reflection.invoker;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.apache.ibatis.reflection.ReflectionException;

public class AmbiguousMethodInvoker extends MethodInvoker {
private final String exceptionMessage;

public AmbiguousMethodInvoker(Method method, String exceptionMessage) {
super(method);
this.exceptionMessage = exceptionMessage;
}

@Override
public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
throw new ReflectionException(exceptionMessage);
}
}


反射调用测试:


package com.laoxu.mybatis.executor;

import org.apache.ibatis.reflection.invoker.AmbiguousMethodInvoker;
import org.apache.ibatis.reflection.invoker.GetFieldInvoker;
import org.apache.ibatis.reflection.invoker.MethodInvoker;
import org.apache.ibatis.reflection.invoker.SetFieldInvoker;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
* 反射测试
*/
public class reflect {

private String one;
private String two;
private String three;

public String getOne() {
return one;
}

public void setOne(String one) {
this.one = one;
}

public String getTwo() {
return two;
}

public void setTwo(String two) {
this.two = two;
}

public String getThree() {
return three;
}

public void setThree(String three) {
this.three = three;
}

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {
// methodInvokerTest();
// getFieldInvokerTest();
setFieldInvokerTest();

}

private static void methodInvokerTest() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException{
// 反射获取类
Class clazz = Class.forName("com.laoxu.mybatis.executor.reflect");
// 获取类中的方法反射
Method helloWorldMethod = clazz.getMethod("helloWorld", String.class);
// 实例化方法调用
MethodInvoker methodInvoker = new MethodInvoker(helloWorldMethod);
// 实例化不确定方法调用,invoke调用后抛初【异常信息】
// AmbiguousMethodInvoker methodInvoker = new AmbiguousMethodInvoker(helloWorldMethod, "异常信息");
// 调用类中的方法
methodInvoker.invoke(new reflect(), new String[]{"test"});
// 打印方法的返回类型
System.out.println(methodInvoker.getType());
/**
* 返回:
* hello world test
* class java.lang.String
*/
}

private static void getFieldInvokerTest() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {
reflect r = new reflect();
r.setOne("1");
r.setTwo("2");
r.setThree("3");
// 反射获取类
Class clazz = Class.forName("com.laoxu.mybatis.executor.reflect");
// 获取类中所有的属性
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
// 实例化方法调用
GetFieldInvoker getFieldInvoker = new GetFieldInvoker(field);
// 调用类中的方法
System.out.println(getFieldInvoker.invoke(r, new String[0]));
// 打印方法的返回类型
System.out.println(getFieldInvoker.getType());
}
/**
* 返回:
* 1
* class java.lang.String
* 2
* class java.lang.String
* 3
* class java.lang.String
*/
}

private static void setFieldInvokerTest() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {
reflect r = new reflect();
// 反射获取类
Class clazz = Class.forName("com.laoxu.mybatis.executor.reflect");
// 获取类中所有的属性
Field[] fields = clazz.getDeclaredFields();
int n = 1;
for (Field field : fields) {
// 实例化方法调用
SetFieldInvoker setFieldInvoker = new SetFieldInvoker(field);
// 调用类中的方法
setFieldInvoker.invoke(r, new String[]{String.valueOf(n)});
// 打印方法的返回类型
System.out.println(setFieldInvoker.getType());
n = n + 1;
}
System.out.println(r.getOne());
System.out.println(r.getTwo());
System.out.println(r.getThree());
/**
* 返回:
* class java.lang.String
* class java.lang.String
* class java.lang.String
* 1
* 2
* 3
*/
}



public String helloWorld(String word){
word = "hello world " + word;
System.out.println(word);
return word;
}

}



反射器封装:


/**
* Copyright 2009-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.reflection;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.ReflectPermission;
import java.lang.reflect.Type;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.ibatis.reflection.invoker.AmbiguousMethodInvoker;
import org.apache.ibatis.reflection.invoker.GetFieldInvoker;
import org.apache.ibatis.reflection.invoker.Invoker;
import org.apache.ibatis.reflection.invoker.MethodInvoker;
import org.apache.ibatis.reflection.invoker.SetFieldInvoker;
import org.apache.ibatis.reflection.property.PropertyNamer;
import org.apache.ibatis.util.MapUtil;

/**
* This class represents a cached set of class definition information that
* allows for easy mapping between property names and getter/setter methods.
*
* @author Clinton Begin
*/
public class Reflector {

private final Class<?> type;
private final String[] readablePropertyNames;
private final String[] writablePropertyNames;
private final Map<String, Invoker> setMethods = new HashMap<>();
private final Map<String, Invoker> getMethods = new HashMap<>();
private final Map<String, Class<?>> setTypes = new HashMap<>();
private final Map<String, Class<?>> getTypes = new HashMap<>();
private Constructor<?> defaultConstructor;

private Map<String, String> caseInsensitivePropertyMap = new HashMap<>();

public Reflector(Class<?> clazz) {
type = clazz;
// 添加构造器
addDefaultConstructor(clazz);
// 添加getter
addGetMethods(clazz);
// 添加setter
addSetMethods(clazz);
// 添加属性
addFields(clazz);
readablePropertyNames = getMethods.keySet().toArray(new String[0]);
writablePropertyNames = setMethods.keySet().toArray(new String[0]);
for (String propName : readablePropertyNames) {
caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
for (String propName : writablePropertyNames) {
caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
}

/**
*检查是否可以控制成员访问。
*
如果可以控制成员的可访问性,则返回{@literal true}
* @since 3.5.0
*/
public static boolean canControlMemberAccessible() {
try {
SecurityManager securityManager = System.getSecurityManager();
if (null != securityManager) {
securityManager.checkPermission(new ReflectPermission("suppressAccessChecks"));
}
} catch (SecurityException e) {
return false;
}
return true;
}
......省略
}





相关推荐

评论 抢沙发

表情

分类选择