Java反射-Method的Invoke方法

2019-09-05   龙德   Java   反射 Method  

一个简简单单的 User 类

public class User {

	private String name;

	private int age;

	public User() {
	}

	public User(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public void print() {
		System.out.println("name: " + this.name + ", age: " + this.age);
	}

	public void print(String sex, String addr) {
		System.out.println("name: " + this.name + ", age: " + this.age + ", sex: " + sex + ", addr: " + addr);
	}

	private void privateMethod() {
		System.out.println("private 方法");
	}

	protected void protectedMethod() {
		System.out.println("protected 方法");
	}

	void defaultMethod() {
		System.out.println("default 方法");
	}

	public static void staticMethod() {
		System.out.println("static 方法");
	}

	public final void finalMethod() {
		System.out.println("final 方法");
	}
}

测试类

public class UserTest {

	public static void main(String[] args) throws Exception {
		// 1.先获取 User 类的 Class 对象
		Class userClass = User.class;
		
		// 2.通过 Class 对象获取 Method 对象,参数是方法名(String methodName)和参数类型(Class<?>... parameterTypes)
		
		// public 修饰的空参方法
		Method print1 = userClass.getMethod("print");
		
		// public 修饰的带参方法
		Method print2 = userClass.getMethod("print", String.class, String.class);
		
		// private 修饰的方法,抛出异常 java.lang.NoSuchMethodException
		// Method privateMethod = userClass.getMethod("privateMethod", null);
		
		// protected 修饰的方法,抛出异常 java.lang.NoSuchMethodException
		// Method protectedMethod = userClass.getMethod("protectedMethod", null);
		
		// default 修饰的方法,抛出异常 java.lang.NoSuchMethodException
		// Method defaultMethod = userClass.getMethod("defaultMethod", null);
		
		// static 方法
		Method staticMethod = userClass.getMethod("staticMethod", null);
		
		// final 方法
		Method finalMethod = userClass.getMethod("finalMethod", null);
		
		// 3.调用 Method 对象的 invoke 方法,将 User 类的实例对象和方法的参数传进去
		User user1 = new User("ZhangSan",10);
		User user2 = new User("LiSi",12);
		print1.invoke(user1);
		print2.invoke(user2,"男","中国");
		staticMethod.invoke(user2);
		finalMethod.invoke(user2);
		
		// 一般的方法调用
		System.out.println("========= 一般的方法调用 ========");
		user1.print();
		user2.print("男","中国");
		user2.staticMethod();
		user2.finalMethod();
	}
}

控制台输出

name: ZhangSan, age: 10
name: LiSi, age: 12, sex: 男, addr: 中国
static 方法
final 方法
========= 一般的方法调用 ========
name: ZhangSan, age: 10
name: LiSi, age: 12, sex: 男, addr: 中国
static 方法
final 方法

可以看到通过 Method 对象调用的 invoke() 方法跟对象.方法名的调用的结果是一样的。

结论

终于明白 JDK 的动态代理为什么能执行原对象的方法了,原来是将 Method 对象和方法参数 args 传进了 InvocationHandler 接口的 invoke(Object proxy, Method method, Object[] args) 方法里,然后通过调用 method.invoke(原对象实例,args) 方法就可以达到调用原对象方法的效果。

public class ObjInterceptor implements InvocationHandler {

		@Override
		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			return method.invoke(obj, args);
		}
	}

Elasticsearch-集群

2019-08-25   龙德   Elasticsearch   Elasticsearch  
环境准备,请确保你已经有了以下环境,(1)3台虚拟机,我是用 VMware 搭建的虚拟机,每台虚拟机的地址如下:192.168.8.4、192.168.8.6、192.168.8.8(2)每台虚拟机都确保安装好了 Elasticsearch

Elasticsearch-Java客户端

2019-08-02   龙德   Elasticsearch   Elasticsearch  
Elasticsearch 官方提供了3种客户端:1.TransportClient,这个客户端在7.0.0弃用,将在8.0版本中删除。2.elasticsearch-rest-client,低级的REST客户端,基于Apache HTTP,支持所有Elasticsearch版本,请求编码和响应解码留给用户实现(自己写JSON)。3.elasticsearch-rest-high-level-client,高级的REST客户端,基于低级客户端,对增删改查进行了封装,提供特定方法的API,不需要用户处理编解码,类似之前的TransportClient,但是兼容性较差,对客户端和集群版本要求较高。

Elasticsearch-基础

2019-07-20   龙德   Elasticsearch   Elasticsearch  

Elasticsearch 是一个 nosql 数据库,它底层基于开源库 Lucene,Elasticsearch 是 Lucene 的封装,隐藏了复杂的操作,提供了 RESTful 风格的 API 和 Java 客户端(其它语言的客户端也有),开箱即用。

数据结构-单向链表

2019-07-08   龙德   数据结构   数据结构 单向链表  

链表的定义

链表是线性表的链式存储结构,由 n 个节点组成,每个节点包含两个元素:数据域和指针域

SpringMVC 集成 Shiro

2019-07-01   龙德   SpringMVC   SpringMVC Shiro  

简介

  • Shiro 是 Apache 的一个安全(权限)框架

Java IO - RandomAccessFile

2019-06-27   龙德   Java   Java  

RandomAccessFile 类是专门处理文件的字节流,与其他文件类不同、也是此类最大的特点是:该类支持对文件的随机访问。

RandomAccessFile 维护着一个偏移量,也叫文件指针

当你用 RandomAccessFile 打开一个文件时,指针的值为 0

读取文件时,指针就会自动向前移动,每读取一个字节,指针就 +1

写入文件时也一样,每写入一个字节,指针就 +1

可以通过 getFilePointer 方法 获取指针,通过 seek 方法设置指针

SpringMVC 常用的注解

2019-06-24   龙德   SpringMVC   SpringMVC 注解  

@Controller

  • 作用

标注当前类是一个控制类,类名不能和注解名一样

  • 例子
@Controller // 标注这是一个控制类,类名不能和注解名一样
@RequestMapping("/book") // 访问父路径
public class BookController {
    ......
}

form 表单转 JSON,后台用 @RequestBody 接收

2019-06-23   龙德   SpringMVC   SpringMVC  

后台代码:

public Result add(@RequestBody Node node){}

前台 form 表单:

<form id="form" action="/admin/node/add" method="post" enctype="multipart/form-data">
  <div class="form-group">
    <label>名称</label>
    <input type="text" name="nodeTitle" id="nodeTitle" class="form-control node-name">
  </div>
  <div class="form-group">
    <label for="">描述</label>
    <textarea name="nodeDesc" rows="7" class="form-control node-desc"></textarea>
  </div>
  <button type="submit" id="btn" class="btnbtn-primary">提交</button>
</form>

表单的 name 要和后台对象的字段一致,否则 Spring 映射的时候会报错。

Mybtis 获取自增主键时报错

2019-06-23   龙德   MyBatis   MyBatis  

dao 层接口

int insert(@Param("node") Node node);

xml 文件

<insert id="insert" parameterType="cn.roothub.bbs.module.node.model.Node" keyProperty="nodeId" useGeneratedKeys="true">

报错信息

org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.executor.ExecutorException: Error getting generated key or setting result to parameter object. Cause: org.apache.ibatis.binding.BindingException: Parameter 'nodeId' not found. Available parameters are [node, param1]

提示获取自增主键时失败,无法找到 nodeId 字段。

可是我明明有 nodeId 字段,get/set 方法也有,怎么会找不到呢?

解决方法

原来是我的 dao 层接口使用了@Param 注解,所以这时候直接指定 keyProperty 属性是无效的,这时候需要通过注解定义的对象名.属性

比如我指定的参数名是 @Param(“node”),那么 keyProperty 就要指定为 node.nodeId

keyProperty="node.nodeId"

这样就能获取到自增主键了

如果你不用 @Param 注解指定参数的名字,那么直接通过 nodeId 是可以获取到自增主键的。