java 的 动态代理是代理模式的一种,其利用jdk自带的反射功能 实现,源码位于 java.lang.reflect 下
动态代理的实现: Proxy类 + InvocationHandler (调用方法处理接口)
第一步:实现自己的 代理处理接口MyInvocationHander,接口给出了规范,需要自己是实现(处理场所)
第二步:jdk 动态代理的契入点是 interface,因此要 设计相应的接口Animal( 请求规范),并同时生产一个子类Dog(请求源-要吃东西),必须有规范证书
第三步:请求源Dog 到处理场所Proxy连接处理接口(MyInvocationHander),处理后 会虚拟出 一个dogB 帮dog 完成吃东西的动作。
直接贴代码:
第一:实现自己的 代理处理接口MyInvocationHander,接口给出了规范,需要自己是实现(处理场所)
package com.test.reflect;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler{
/**
* 原告
*/
private Object target;
public MyInvocationHandler(Object target){
this.target = target;
}
/**
* 执行代理对象的所有方法时都会被替换成执行如下的invoke方法
*
* proxy :代表动态代理对象; method:代表正在执行的方法 ;args :代表执行代理对象方法时传入的实参
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
before();
method.invoke(target, args);
after();
return null;
}
public void before(){
System.out.println("before ...");
}
public void after(){
System.out.println("after ...");
}
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
}
第二:jdk 动态代理的契入点是 interface,因此要 设计相应的接口Animal( 请求规范),并同时生产一个子类Dog(请求源-要吃东西),必须有规范证书
package com.test.reflect;
/**
* jdk 动态代理--切入点是 接口
*
* 目标接口
* @author zhangqingzhou
*
*/
public interface Animal {
public void eat();
}
package com.test.reflect;
/*
* 目标类
*/
public class Dog implements Animal{
@Override
public void eat() {
System.out.println(" The dog is like eatting");
}
}
第三:请求源Dog 到处理场所Proxy连接处理接口(MyInvocationHander),处理后 会虚拟出 一个dogB 帮dog 完成吃东西的动作。
package com.test.reflect;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/**
* 动态代理工厂,把真是的对象发进入
* 出来 代理对象
* @author zhangqingzhou
*
*/
public class MyProxyFactory {
public static Object getProxy(Object obj){
InvocationHandler InvocationHander =new MyInvocationHandler(obj);
Object o= Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), InvocationHander);
return o;
}
}
package com.test.reflect;
public class Test {
public static void main(String[] args) {
Animal dog = new Dog();
Animal proxyDog =(Animal) MyProxyFactory.getProxy(dog);
proxyDog.eat();
/**
* console
* before ...
The dog is like eatting
after ...
*/
}
}
可以看到,我们可以通过这种方式 进行拦截时操作 在目的操作前后可以加上自己想要的操作,那么你是否会想到 spring -aop 面向切面编程 原理喝着一样,比如 操作失败 进行数据回滚操作;但此方式 要求必须实现接口(jdk动态代理要求),若是 class 则需要使用 cglib,在配置文件中可以设置 AOP 代理方式;