首页 体育 教育 财经 社会 娱乐 军事 国内 科技 互联网 房产 国际 女人 汽车 游戏

Java反射机制与动态代理

2020-01-20

测验代码:

private static void testMethods throws Exception {

// 1. 获取一切 public 办法

Method[] methods = aClass.getMethods;

for {

System.out.println;

}

// 2. 获取该类声明的一切办法

Method[] declaredMethods = aClass.getDeclaredMethods;

for {

System.out.println;

}

// 4. 获取指定的办法并调用

Method method = aClass.getDeclaredMethod;

method.setAccessible; // 修正拜访权限

System.out.println);

System.out.println));

Object instance = aClass.newInstance;

System.out.println);

}

private static void testMethods throws Exception {

// 1. 获取一切 public 办法

Method[] methods = aClass.getMethods;

for {

System.out.println;

}

// 2. 获取该类声明的一切办法

Method[] declaredMethods = aClass.getDeclaredMethods;

for {

System.out.println;

}

// 4. 获取指定的办法并调用

Method method = aClass.getDeclaredMethod;

method.setAccessible; // 修正拜访权限

System.out.println);

System.out.println));

Object instance = aClass.newInstance;

System.out.println);

}

输出成果:

// getMethods 办法回来成果:

// Person 类的 public 办法:

method-- public java.lang.String com.jaxer.example.reflection.Person.toString

method-- public java.lang.String com.jaxer.example.reflection.Person.getName

method-- public void com.jaxer.example.reflection.Person.setName

method-- public void com.jaxer.example.reflection.Person.setAge

method-- public int com.jaxer.example.reflection.Person.getAge

// Human 类的 public 办法:

method-- public void com.jaxer.example.reflection.Human.hi

// Object 类的 public 办法:

method-- public final void java.lang.Object.wait throws java.lang.InterruptedException

method-- public final native void java.lang.Object.wait throws java.lang.InterruptedException

method-- public final void java.lang.Object.wait throws java.lang.InterruptedException

method-- public boolean java.lang.Object.equals

method-- public native int java.lang.Object.hashCode

method-- public final native java.lang.Class java.lang.Object.getClass

method-- public final native void java.lang.Object.notify

method-- public final native void java.lang.Object.notifyAll


// getDeclaredMethods 办法回来成果:

declaredMethod-- public java.lang.String com.jaxer.example.reflection.Person.toString

declaredMethod-- public java.lang.String com.jaxer.example.reflection.Person.getName

declaredMethod-- public void com.jaxer.example.reflection.Person.setName

declaredMethod-- private void com.jaxer.example.reflection.Person.test

declaredMethod-- public void com.jaxer.example.reflection.Person.setAge

declaredMethod-- public int com.jaxer.example.reflection.Person.getAge


// 调用 test 办法:

办法名:private void com.jaxer.example.reflection.Person.test

办法修饰符:private

test is invoked.

null

// getMethods 办法回来成果:

// Person 类的 public 办法:

method-- public java.lang.String com.jaxer.example.reflection.Person.toString

method-- public java.lang.String com.jaxer.example.reflection.Person.getName

method-- public void com.jaxer.example.reflection.Person.setName

method-- public void com.jaxer.example.reflection.Person.setAge

method-- public int com.jaxer.example.reflection.Person.getAge

// Human 类的 public 办法:

method-- public void com.jaxer.example.reflection.Human.hi

// Object 类的 public 办法:

method-- public final void java.lang.Object.wait throws java.lang.InterruptedException

method-- public final native void java.lang.Object.wait throws java.lang.InterruptedException

method-- public final void java.lang.Object.wait throws java.lang.InterruptedException

method-- public boolean java.lang.Object.equals

method-- public native int java.lang.Object.hashCode

method-- public final native java.lang.Class java.lang.Object.getClass

method-- public final native void java.lang.Object.notify

method-- public final native void java.lang.Object.notifyAll


// getDeclaredMethods 办法回来成果:

declaredMethod-- public java.lang.String com.jaxer.example.reflection.Person.toString

declaredMethod-- public java.lang.String com.jaxer.example.reflection.Person.getName

declaredMethod-- public void com.jaxer.example.reflection.Person.setName

declaredMethod-- private void com.jaxer.example.reflection.Person.test

declaredMethod-- public void com.jaxer.example.reflection.Person.setAge

declaredMethod-- public int com.jaxer.example.reflection.Person.getAge


// 调用 test 办法:

办法名:private void com.jaxer.example.reflection.Person.test

办法修饰符:private

test is invoked.

null

结构中常用的反射机制首要是以上那些,这儿暂不深究其完成原理,今后有需求再行弥补。下面扼要剖析署理相关的内容。

运用署理的首要意图:对方针方针进行功用增强,例如 Spring 的 AOP。

既然是对方针方针的办法进行增强,署理方针的办法中一定会调用方针方针的办法。而且一般会在方针方针的办法调用前后做一些其他的处理以到达增强的作用。

署理办法一般分为「静态署理」和「动态署理」,静态署理运用较少;而动态署理常用的有 JDK 动态署理和 CGLib 动态署理。下面扼要剖析。

一个一般的 Java 接口及其完成类如下:

// 接口

public interface UserService {

void save;

}


// 完成类

public class UserServiceImpl implements UserService {

@Override

public void save {

System.out.println;

}

}

// 接口

public interface UserService {

void save;

}


// 完成类

public class UserServiceImpl implements UserService {

@Override

public void save {

System.out.println;

}

}

不管静态署理仍是动态署理,都是对该类的 save 办法进行增强。

此处以在该办法履行前后各打印一句话来演示。

首要思维:创立一个 UserService 接口的完成类 UserServiceProxy,而且该类持有 UserServiceImpl 方针,在 UserServiceProxy 类的 save 办法中调用 UserServiceImpl 的 save 办法,示例代码如下:

public class UserServiceProxy implements UserService {

private UserService userService;


public UserServiceProxy {

this.userService = userService;

}


@Override

public void save {

System.out.println;

userService.save; // 调用方针类的办法

System.out.println;

}

}

public class UserServiceProxy implements UserService {

private UserService userService;


public UserServiceProxy {

this.userService = userService;

}


@Override

public void save {

System.out.println;

userService.save; // 调用方针类的办法

System.out.println;

}

}

测验代码:

private static void testStaticProxy {

UserService userService = new UserServiceImpl;

UserService proxy = new UserServiceProxy;

proxy.save;

}


/* 运转成果:

---静态署理:办法履行前---

保存用户:jack

---静态署理:办法履行后---

*/

private static void testStaticProxy {

UserService userService = new UserServiceImpl;

UserService proxy = new UserServiceProxy;

proxy.save;

}


/* 运转成果:

---静态署理:办法履行前---

保存用户:jack

---静态署理:办法履行后---

*/

清楚明了,运用 UserServiceProxy 能够增强 UserServiceImpl 的 save 办法。但由于代码是固定的,不行灵敏,因而静态署理运用较少,一般运用动态署理。

PS: 此处代码完成办法或许不尽相同,但思路附近。

与静态署理比较,动态署理则是在运转时动态生成一个署理类,该类能够对方针方针的办法进行功用增强。动态署理常用的有 JDK 动态署理和 CGLib 动态署理,下面扼要剖析。

JDK 的动态署理完成办法:

运用 Proxy 类的 newProxyInstance 办法创立署理方针,运用 InvocationHandler 来完成增强的逻辑。示例代码如下:

// JDK 署理工厂,作用是生成署理方针

public class JDKProxyFactory {

// 获取 target 的署理方针

public Object getProxy {

return Proxy.newProxyInstance.getClassLoader,

target.getClass.getInterfaces, new MyInvocationHandler);

}

// 自定义 InvocationHandler

private static class MyInvocationHandler implements InvocationHandler {

// 方针方针

private Object target;


public MyInvocationHandler {

this.target = target;

}

// 完成增强逻辑

@Override

public Object invoke throws Throwable {

System.out.println;

Object result = method.invoke; // 调用方针方针的办法

System.out.println;

return result;

}

}

}

// JDK 署理工厂,作用是生成署理方针

public class JDKProxyFactory {

// 获取 target 的署理方针

public Object getProxy {

return Proxy.newProxyInstance.getClassLoader,

target.getClass.getInterfaces, new MyInvocationHandler);

}

// 自定义 InvocationHandler

private static class MyInvocationHandler implements InvocationHandler {

// 方针方针

private Object target;


public MyInvocationHandler {

this.target = target;

}

// 完成增强逻辑

@Override

public Object invoke throws Throwable {

System.out.println;

Object result = method.invoke; // 调用方针方针的办法

System.out.println;

return result;

}

}

}

测验代码:

private static void testJdkProxy {

UserService userService = new UserServiceImpl; // 方针方针

JDKProxyFactory jdkProxyFactory = new JDKProxyFactory; // 署理工厂

// 运用署理工厂生成署理方针

UserService proxy = jdkProxyFactory.getProxy;

proxy.save; // 调用署理方针的办法

}


/* 运转成果:

方针类办法履行前-----

保存用户:jack

方针类办法履行后-----

*/

private static void testJdkProxy {

UserService userService = new UserServiceImpl; // 方针方针

JDKProxyFactory jdkProxyFactory = new JDKProxyFactory; // 署理工厂

// 运用署理工厂生成署理方针

UserService proxy = jdkProxyFactory.getProxy;

proxy.save; // 调用署理方针的办法

}


/* 运转成果:

方针类办法履行前-----

保存用户:jack

方针类办法履行后-----

*/

完成原理可参阅:https://blog.csdn.net/yhl_jxy/article/details/80586785

首要思路:

创立一个方针类的子类 Enhancer,在子类中设置回调方针,并在回调办法中完成对方针方针的增强功用逻辑。示例代码如下:

// CGLIB 工厂,用于生成署理方针

public class CglibProxyFactory {

// 获取署理方针

public Object getProxy {

Enhancer enhancer = new Enhancer;

enhancer.setSuperclass);

enhancer.setCallback); // 设置回调

return enhancer.create;

}


// 自定义办法阻拦 MethodInterceptor

private static class MyMethodInterceptor implements MethodInterceptor {

@Override

public Object intercept throws Throwable {

System.out.println;

Object o = proxy.invokeSuper; // 调用方针方针的办法

System.out.println;

return o;

}

}

}

// CGLIB 工厂,用于生成署理方针

public class CglibProxyFactory {

// 获取署理方针

public Object getProxy {

Enhancer enhancer = new Enhancer;

enhancer.setSuperclass);

enhancer.setCallback); // 设置回调

return enhancer.create;

}


// 自定义办法阻拦 MethodInterceptor

private static class MyMethodInterceptor implements MethodInterceptor {

@Override

public Object intercept throws Throwable {

System.out.println;

Object o = proxy.invokeSuper; // 调用方针方针的办法

System.out.println;

return o;

}

}

}

测验代码:

private static void testCglibProxy {

UserService userService = new UserServiceImpl;

CglibProxyFactory cglibProxyFactory = new CglibProxyFactory;

UserService proxy = cglibProxyFactory.getProxy;

proxy.save;

}


/* 运转成果:

cglib办法调用前

保存用户:jack

cglib办法调用后

*/

private static void testCglibProxy {

UserService userService = new UserServiceImpl;

CglibProxyFactory cglibProxyFactory = new CglibProxyFactory;

UserService proxy = cglibProxyFactory.getProxy;

proxy.save;

}


/* 运转成果:

cglib办法调用前

保存用户:jack

cglib办法调用后

*/

PS: 运用 CGLib 需求导入第三方 jar 包。

完成原理可参阅:https://blog.csdn.net/yhl_jxy/article/details/80633194

二者首要差异:

热门文章

随机推荐

推荐文章