jdk 源码分析(21)java 动态代理和反射
2017-08-09 23:09
711 查看
java动态代理用在很多地方。spring框架,RPC框架中都使用了动态代理,动态代理很重要。
首先看看静态代理:
相对静态代理而已,静态代理需要对每一个方法做一次处理。如下:
定义一个实体列,交个代理类,然后由代理帮忙做事
接口
实体类:
代理类:
,如果实体类有多个方法,那么静态的代理类就需要复写多个方法,哪怕是做同样的事情,所以就出现动态代理。
添加一个动态代理类:
然后在看测试类:
从这里看动态类和静态的没有什么区别,但是如果接口添加一个方法,那么静态代理类将必须重写这个方法,但是动态代理就不需要,可以直接调用,
这就是动态代理的好处,比如在做web的拦截器时,只需要在
System.out.println("I
am Manager, I am help other find job"); 改为对method的判断或者
对参数的判断,就可以达到拦截的处理。比如
if(method.getName.endwith(".jpg")){
return null;
}
接下来看看proxy底层代码是怎么实现的。
final Class<?>[] intfs = interfaces.clone();
//安全判断,一般不会设置安全问题
底层就是通过反射完成的。
首先看看静态代理:
相对静态代理而已,静态代理需要对每一个方法做一次处理。如下:
定义一个实体列,交个代理类,然后由代理帮忙做事
public static void main(String[] args) {
People people = new Students();
ProxyManager proxyManager = new ProxyManager(people);
proxyManager.findJob();
}
接口
public interface People {
public void findJob();
}
实体类:
public class Students implements People{
@Override
public void findJob() {
System.out.println("I am student ,I am looking for a job");
}
}
代理类:
public class ProxyManager implements People {
People people ;
public ProxyManager(People people){
this.people = people;
}
@Override
public void findJob() {
System.out.println("I am Manager, I am help other find job");
people.findJob();
System.out.println("");
}
}
,如果实体类有多个方法,那么静态的代理类就需要复写多个方法,哪怕是做同样的事情,所以就出现动态代理。
添加一个动态代理类:
public class ProxyD {
Class target;
Object object;
public ProxyD(Class target,Object object){
this.target=target;
this.object=object;
}
public Object getPeopele() throws Throwable{
return Proxy.newProxyInstance(target.getClassLoader(),
new Class[]{target}, new ObjectHandle(this.object));
}
class ObjectHandle implements InvocationHandler{
Object target;
public ObjectHandle(Object object) {
this.target = object;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("I am Manager, I am help other find job");
Object o = method.invoke(target, args);
System.out.println("");
return o;
}
}
}
然后在看测试类:
People people = new Students();
ProxyD proxyD=new ProxyD(People.class,people);
People proxyManager =(People) proxyD.getPeopele();
proxyManager.findJob();
从这里看动态类和静态的没有什么区别,但是如果接口添加一个方法,那么静态代理类将必须重写这个方法,但是动态代理就不需要,可以直接调用,
People people = new Students();
ProxyD proxyD=new ProxyD(People.class,people);
People proxyManager =(People) proxyD.getPeopele();
proxyManager.findJob();
proxyManager.findGirl();
这就是动态代理的好处,比如在做web的拦截器时,只需要在
System.out.println("I
am Manager, I am help other find job"); 改为对method的判断或者
对参数的判断,就可以达到拦截的处理。比如
if(method.getName.endwith(".jpg")){
return null;
}
接下来看看proxy底层代码是怎么实现的。
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
//接口复制
final Class<?>[] intfs = interfaces.clone();
//安全判断,一般不会设置安全问题
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* Look up or generate the designated proxy class.
*/
//去缓存查看是否已经生成过,如果生存过直接获取。没有就生存并保存到缓存中
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
//获取类的构造函数
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
//如果私有,需要设置setAccessible为true才能读取
cons.setAccessible(true);
return null;
}
});
}
//反射生存对象
return cons.newInstance(new Object[]{h});
...
...
}
底层就是通过反射完成的。
相关文章推荐
- Java动态代理详解,以及底层JDK源码实现分析(基于Java8)。
- Java基础:JDK动态代理源码分析
- JAVA 动态代理(proxy)的实现和源码分析
- Java设计模式-代理模式之动态代理(附源码分析)
- Java动态代理的源码分析;Proxy与InvocationHandler
- Java反射—运用反射生成jdk动态代理
- Java 反射之JDK动态代理
- 转 MyBatis Mapper 接口如何通过JDK动态代理来包装SqlSession 源码分析
- java反射之基于JDK的动态代理的乐子
- 【Java】从源码分析动态代理机制
- Java反射之JDK动态代理实现简单AOP
- Mybatis3源码分析(21)-Mapper实现-动态代理
- 动态代理及JDK动态代理源码分析
- Java 动态代理源码分析
- Java JDK 动态代理(AOP)使用及实现原理分析
- MyBatis Mapper 接口如何通过JDK动态代理来包装SqlSession 源码分析
- java动态代理Proxy源码解析(Jdk 1.6)
- java反射——运用反射生成jdk动态代理
- Java 动态代理源码分析