快上网专注成都网站设计 成都网站制作 成都网站建设
成都网站建设公司服务热线:028-86922220

网站建设知识

十年网站开发经验 + 多家企业客户 + 靠谱的建站团队

量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决

Java动态代理的理解与Cglib动态代理实现-创新互联

什么是动态代理?

在嘉峪关等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供成都网站制作、网站建设 网站设计制作按需求定制开发,公司网站建设,企业网站建设,品牌网站设计,成都营销网站建设,外贸营销网站建设,嘉峪关网站建设费用合理。

先说下静态代理:

也即是说,在程序运行前,已经有了编译好的类,这个就是静态代理,

动态代理:

也即,在程序运行前, 代理类并不存在,而是在程序运行时,动态生成的类是动态代理类。

可能会有如下思考

代理模式是怎样的?用什么技术实现?

为什么要使用代理模式呢?有什么好处?

动态代理的应用场景有哪些?

先说说动态代理的实现吧:

动态代理主要使用的是Java 反射技术:

JavaAPI 中关于InvocationHandler有大致这么一段描述,每个代理类都要实现InvocationHandler这个接口,每个代理类都会关联到一个handle,

当一个代理类调用方法时,会转到InvocationHandler的Invoke方法进行调用。

以下代码有引用以为牛人代码

看下InvocationHandler源码,我这就不再写一遍了。

public interface InvocationHandler

{

public abstract Object invoke(Object obj, Method method, Object aobj[])

throws Throwable;

}

这个invoke方法中有几个参数 :

obj:表示我们要调用的真实对象

method:表示我们要调用的真实对象的某个方法。

aobj[] :表示真实对象某个方法接受的参数。

怎么用这个InvocationHandler 这个接口,主要看proxy这个类:

Proxy是创建一个代理对象的类

Proxy这个类有这个一个方法:是用的最多的方法

public static Object newProxyInstance(ClassLoader classloader, Class aclass[], InvocationHandler invocationhandler)

throws IllegalArgumentException

参数:

classloader: 定义了由那个ClassLoader对对象进行加载

aclass[]: 是为代理对象提供了哪些接口,表示代理对象实现了这些接口,

invocationhandler: 表示代理对象调用方法时会关联到那个invocationhandler

主要通过类Proxy与接口invocationhandler实现动态代理:

看下具体动态代理实现加深理解:

1.首先肯定是需要一个接口的:

public interface UserService {

public String getName(int id);

public Integer getAge(int id);

}

还需要这个接口的实现,也就是代理对象:

public class UserServiceImpl implements UserService {

@Override

public String getName(int id) {

System.out.println("------getName------");

return "Tom";

}

@Override

public Integer getAge(int id) {

System.out.println("------getAge------");

return 10;

}

}

还需要自定义一个invocationhandler ,自己实现invoke方法:

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler {

private Object target;

MyInvocationHandler() {

super();

}

MyInvocationHandler(Object target) {

super();

this.target = target;

}

@Override

public Object invoke(Object o, Method method, Object[] args) throws Throwable {

if("getName".equals(method.getName())){

System.out.println("++++++before " + method.getName() + "++++++");

Object result = method.invoke(target, args);

System.out.println("++++++after " + method.getName() + "++++++");

return result;

}else{

Object result = method.invoke(target, args);

return result;

}

}

}

最后再看下proxy是怎样的使用这个接口,还有invocationhandler的

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Proxy;

public class TestProxy {

public static void main(String[] args) {

UserService userService = new UserServiceImpl();

InvocationHandler invocationHandler = new MyInvocationHandler(userService);

UserService userServiceProxy = (UserService)Proxy.newProxyInstance(userService.getClass().getClassLoader(),

userService.getClass().getInterfaces(), invocationHandler);

System.out.println(userServiceProxy.getName(1));

System.out.println(userServiceProxy.getAge(1));

}

}

以上可以看到可以清晰理解proxy的newproxyInstance是用来生成代理对象的, userService是指向具体 的实现

UserServiceImpl

给newproxyInstance方法传入实际的classLoader,实际类对应的接口,与调用类方法的invocationhandler即可实现:

System.out.println("++++++before " + method.getName() + "++++++");

其实上面这个一行代码就有***性质,aop时再详细讨论.

上面可以看到 使用这个反射技术实现动态代理,需要定义一个接口,但是有时候其实不想定义接口,只希望定义好实现类,然后你再在方法运行前,运行后加些内容即可。

这个就考虑了一个CGLIB这个可是不错的使用CGLIB实现动态代理很方便。

Cglib 采用的是ASM字节码技术,利用字节码生成代理类。效率比反射要高,但是不能代理final修身的类,clglib元素是集成被代理的类。final类不能被继承。

下面看下cglib具体实现:

下载 cglib包和asm包,你的工程需要依赖这两个包:

首先需要一个非final类,不再和反射一样需要一个接口了

public class StudentService {

public String getName(){

System.out.println("------getName------");

return "Tom";

}

public Integer getID(){

System.out.println("------getID------");

return 10;

}

}

接下来就看怎么代理上面的类了,需要定义一个拦截器:

import net.sf.cglib.proxy.MethodInterceptor;

import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibProxy implements MethodInterceptor {

@Override

public Object intercept(Object o, Method method, Object[] args,

MethodProxy methodProxy) throws Throwable {

System.out.println("++++++before " + methodProxy.getSuperName()

+ "++++++");

System.out.println(method.getName());

Object o1 = methodProxy.invokeSuper(o, args);

System.out.println("++++++before " + methodProxy.getSuperName()

+ "++++++");

return o1;

}

}

上面的interceptf方法和invocationhandler中的invoke方法类似,通过interceptf来真正调用方法invokeSuper:

最后看下Cglb具体怎么代理StudentService这个类吧:

import net.sf.cglib.proxy.Enhancer;

public class TestCglib {

public static void main(String[] args) {

CglibProxy cglibProxy = new CglibProxy();

Enhancer enhancer = new Enhancer();

enhancer.setSuperclass(StudentService.class);

enhancer.setCallback(cglibProxy);

StudentService o = (StudentService)enhancer.create();

System.out.println(o.getName());

// System.out.println(o.getID());

}

}

上面的o即是 代理类,该类可以访问真实的Studentservice方法:

运行结果:无锡妇科检查多少钱 http://www.120csfkyy.com/

++++++before CGLIB$getName$1++++++

getName

------getName------

++++++before CGLIB$getName$1++++++

Tom

使用Cglib 有啥好处?

看下面代码:

public class TestCglib {

public static void main(String[] args) {

CglibProxy cglibProxy = new CglibProxy();

Enhancer enhancer = new Enhancer();

enhancer.setSuperclass(StudentService.class);

enhancer.setCallback(cglibProxy);

StudentService o = (StudentService)enhancer.create();

System.out.println(o.getName());

// System.out.println(o.getID());

Enhancer enhancer1 = new Enhancer();

enhancer1.setSuperclass(UserServiceImpl.class);

enhancer1.setCallback(cglibProxy);

UserServiceImpl obj = (UserServiceImpl)enhancer1.create();

System.out.println(obj.getName(1));

// System.out.println(o.getID());

}

}

只要写一个

cglibProxy

就可以是实现

对UserServiceImpl 与 StudentService进行代理

减少了代码的繁琐,只有有这么一个代理就够了,其次方便维护,解耦合,要是有问题,只要去找 原始类就可以了

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


分享标题:Java动态代理的理解与Cglib动态代理实现-创新互联
本文路径:http://6mz.cn/article/dhcegs.html

其他资讯