前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >拦截器反射机制/动态代理(拦截器。通过接口调实现类也是反射实现的?)和代理模式

拦截器反射机制/动态代理(拦截器。通过接口调实现类也是反射实现的?)和代理模式

原创
作者头像
Java栈
修改2019-07-26 09:17:56
9000
修改2019-07-26 09:17:56
举报
文章被收录于专栏:Java栈

反射机制:

1.获得Class的实例c:如Class.forName("包路径.类名");

2.创建对象:

1》c.newInstance();直接调用无参构造函数创建对象,已过时

2》先获取构造函数再创建对象

getDeclaredConstructor(Class<?>... parameterTypes) 

返回指定参数类型的所有构造器,包括public的和非public的,当然也包括private的。

getDeclaredConstructors()的返回结果就没有参数类型的过滤了。

getConstructor(Class<?>... parameterTypes)

只返回制定参数类型访问权限是public的构造器。

getConstructors()的返回结果同样也没有参数类型的过滤。

// 获取所有的构造函数

Constructor<?> cons[] = c.getConstructors();

f1 = (Foo) cons[0].newInstance();

f2 = (Foo) cons[1].newInstance("abc");

3.上面的两步走完已经可以通过创建的目标对象的实例去访问其属性或调用其方法,也可以如下:

Foo f = new Foo();

Method method = f.getClass().getMethod("print", new Class<?>[0]);(class实例不仅可以获取构造方法,方法,还有属性)

method.invoke(f);

http://www.cnblogs.com/fangjian0423/p/springMVC-interceptor.html

Web请求被DispatcherServlet截获后,会调用DispatcherServlet的doDispatcher方法。

https://www.cnblogs.com/wxgblogs/p/5849435.html

SpringMVC具有统一的入口DispatcherServlet,所有的请求都通过DispatcherServlet。

  DispatcherServlet是前置控制器,配置在web.xml文件中的

DispatcherServlet继承自HttpServlet(含get,post的那个servlet?)

之前的AOP是拦截的方法,拦截器怎么实现的拦截url?

代理模式:

代理模式分三种:静态代理,JDK动态代理,CGlib动态代理

静态代理功能点实现机制:

1.代理角色和真实角色共同实现同一抽象角色(接口或抽象类)。这一规定是为了约束代理角色要保持和真实角色一样的功能,这样才叫代理。

2.代理角色的拦截实现机制:

代理角色方法(){

     代理角色方法自定义逻辑;

     真实角色调用自己的方法;

      代理角色方法自定义逻辑;

}

静态代理缺点:

1.代理类要实现接口的所有方法,接口中方法多时较麻烦。

2.接口有改动时,委托类和代理类都要改动维护。

JDK动态代理:

创建委托接口的代理类:

God proxy = (God) (Proxy.newProxyInstance(God.class.getClassLoader(), new Class[]{God.class}, inter));//接口类加载器,接口Class类实例,中介类实例。

@CallerSensitive

public static Object newProxyInstance(ClassLoader loader,

Class<?>[] interfaces,

InvocationHandler h)

。。。。。。

Class<?> cl = getProxyClass0(loader, intfs);

try {

final Constructor<?> cons = cl.getConstructor(constructorParams);

final InvocationHandler ih = h;

if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {

// create proxy instance with doPrivilege as the proxy class may

// implement non-public interfaces that requires a special permission

return AccessController.doPrivileged(new PrivilegedAction<Object>() {

public Object run() {

return newInstance(cons, ih);

}

});

} else {

return newInstance(cons, ih);

}

。。。。。。

}

通过getProxyClass0(loader, intfs)得到代理类的Class对象,然后通过Class对象得到构造方法,进而创建代理对象。下一步看getProxyClass0这个方法

private static Class<?> getProxyClass0(ClassLoader loader,

Class<?>... interfaces) {

。。。。。。

return proxyClassCache.get(loader, interfaces);

}

查看get方法:

public V get(K key, P parameter) {

。。。。。。

Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));

。。。。。。

}

查看apply方法:

@Override

public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {

。。。。。。

/*

* Generate the specified proxy class.

*/

byte[] proxyClassFile = ProxyGenerator.generateProxyClass(

proxyName, interfaces);

try {

return defineClass0(loader, proxyName,

proxyClassFile, 0, proxyClassFile.length);

}

。。。。。。

}

}

生成的代理类的子类方法:

public final void outputTest2()

  。。。。。。

      this.h.invoke(this, m3, null);

 。。。。。。

  }

h是代理类Proxy的属性:

public class Proxy implements java.io.Serializable {

private static final long serialVersionUID = -2222568056686623797L;

。。。。。。

protected InvocationHandler h;

。。。。。。

}

查看生成的代理类子类:

//class.getInterfaces(); 获取指定class实例实现的接口class

byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy0", TargetObject.class.getInterfaces());

FileOutputStream out = null;

try {

out = new FileOutputStream(path);

out.write(classFile);

out.flush();

} catch (Exception e) {

e.printStackTrace();

} finally {

try {

out.close();

} catch (IOException e) {

e.printStackTrace();

}

}

JDK动态代理原理总结:

在中介类的invoke方法中配置拦截逻辑,invoke方法入参之一是Method,只要传入不同的Method即可实现通用拦截。

以接口类加载器,接口Class,中介类实例为入参调用代理类的创建代理方法:

Proxy.newProxyInstance(接口类加载器, 接口class,中介类实例);

此方法:1.将中介类实例赋值给代理类 

               2.反射机制生成代理类的子类(子类方法中调用父类的中介类属性的invoke方法。)

与静态代理对比:

静态代理:接口,委托角色,代理角色(1.实现同名方法。2.同名方法实现拦截逻辑)

动态代理:接口,委托角色,中介类(invoke方法以方法名为入参实现通用拦截),代理角色(1.含中介类属性用来调用中介类),代理角色子类(1.实现同名方法。2.同名方法通过父类的中介类属性来调用中介类的invoke方法)

代理调用的某个方法是怎么将该方法映射到Method传给invoke方法的?

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档