Java动态代理为实例对象提供一个模仿者,这个模仿者不仅可以拥有真实类的行为,还可以自定义的添加一些内容;aop中大量的应用了动态代理机制。
jdk代理根据类的接口生成代理,因此jdk只能为实现了接口的类进行代理。
package jyl.mix.proxy.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyCustomInvocationHandler<T> implements InvocationHandler{
private Logger logger = LoggerFactory.getLogger(this.getClass());
private T obj;
public MyCustomInvocationHandler(T obj){
this.obj = obj;
}
/**
* invoke
* 最终通过native方法NativeMethodAccessorImpl.invoke0调用jvm的底层代码
* openjdk中为Java_sun_reflect_NativeMethodAccessorImpl_invoke0(NativeAccessors.c),
* JVM_InvokeMethod(jvm.cpp)
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
logger.info("before method invoke");
Object retObj = method.invoke(obj, args);
logger.info("after method invoke");
return retObj;
}
/**
* Proxy.newProxyInstance,
* 生成Proxy内部实现Proxy.newProxyInstance
* 1.利用classloader和类实现的interfaces两个作为参数,生成匿名代理类Class对象
* 2.将invocationHandler作为参数,调用代理类的构造方法产生Proxy对象
* @return
*/
public T getProxy(){
return (T)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), obj.getClass().getInterfaces(),
this);
}
}
package jyl.mix.proxy.jdk;
public interface TestInterfaceGet {
String shouInfo();
}
package jyl.mix.proxy.jdk;
public interface TestInterfaceSet {
void setNameAge(String name, Integer age);
}
package jyl.mix.proxy.jdk;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TestInterfaceImpl implements TestInterfaceGet,TestInterfaceSet {
private Logger logger = LoggerFactory.getLogger(this.getClass());
private String name;
private Integer age;
@Override
public String shouInfo() {
String info = "name = " + this.name + ",age = " + this.age ;
logger.info(info);
return info;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public void setNameAge(String name, Integer age) {
this.setName(name);
this.setAge(age);
}
}
package jyl.mix.proxy.jdk;
/**
*jdk代理
*
*
*/
public class TestProxy {
public static void main(String args[]){
TestInterfaceImpl xiaoming = new TestInterfaceImpl();
TestInterfaceSet proxyWrite = new MyCustomInvocationHandler<TestInterfaceSet>(xiaoming).getProxy();
proxyWrite.setNameAge("xiaoming", 10);
TestInterfaceGet proxyRead = new MyCustomInvocationHandler<TestInterfaceGet>(xiaoming).getProxy();
proxyRead.shouInfo();
TestInterfaceGet proxyRead2 = (TestInterfaceGet)new MyCustomInvocationHandler<TestInterfaceSet>(xiaoming).getProxy();
proxyRead2.shouInfo();
TestInterfaceImpl proxyXiaoming = (TestInterfaceImpl)new MyCustomInvocationHandler<TestInterfaceSet>(xiaoming).getProxy();
proxyXiaoming.shouInfo();
}
}