方式一:传统的代理

package cn.hc.domain;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; /**
* 代理对象创建的工厂类
* @author hc
*
*/
public class JDKProxyFactory implements InvocationHandler{
//被代理对象
private Object target;
public JDKProxyFactory(Object target){
this.target=target;
}
//创建代理
public Object createProxy(){
//三个参数:类加载器 实现接口 invocationHandler
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
public Object invoke(Object arg0, Method arg1, Object[] arg2)
throws Throwable {
// TODO Auto-generated method stub
//调用目标真是的方法
System.out.println("日志已经被记录");
return arg1.invoke(target, arg2);
}
}

此种方法的缺陷在于:被代理的类必须实现接口

package cn.hc.domain;
//代理对象的接口
public interface UserDao {
public void save();
public void update();
}package cn.hc.domain;
/**
* 被代理的目标对象
* @author hc
*
*/
public class UserDaoImpl implements UserDao { public void save() {
// TODO Auto-generated method stub
System.out.println("添加用户");
} public void update() {
// TODO Auto-generated method stub
System.out.println("更新用户");
} }
//测试类package cn.hc.domain; import org.junit.Test; public class TestProxy {
@Test
public void testJdkProxy(){
//测试jdk动态代理
//1真实目标对象
UserDao userDao=new UserDaoImpl();
//System.out.println(userDao);
UserDao proxy=(UserDao) new JDKProxyFactory(userDao).createProxy();
proxy.save();
proxy.update();
}
}

测试结果:

日志已经被记录

添加用户

日志已经被记录

更新用户

方式2:cglib动态代理

package cn.hc.cglibProxy;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy; public class CGlibProxyFactory implements MethodInterceptor{
private Object target;
public CGlibProxyFactory(Object target){
this.target=target;
}
//创建代理对象的方法
public Object createProxy() {
//创建Enhance对象
Enhancer enhancer=new Enhancer();
//cglib创建代理,对目标对象创建子类对象
enhancer.setSuperclass(target.getClass());
//传入callback对象,对目标增强
enhancer.setCallback(this);
return enhancer.create();
}
//arg3 用于执行父类的方法
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
// TODO Auto-generated method stub
System.out.println("开始记录日志");
return arg1.invoke(target,arg2);
}
}
package cn.hc.cglibProxy;

public class ProductDao {
public void add(){
System.out.println("添加");
}
public void delete(){
System.out.println("删除");
}
}
//测试方法
package cn.hc.cglibProxy; import org.junit.Test; public class CGlibTest {
@Test
public void test1(){
//创建目标对象
ProductDao dao=new ProductDao();
ProductDao proxy=(ProductDao) new CGlibProxyFactory(dao).createProxy();
proxy.add();
proxy.delete();
}
}

Java动态代理的两种实现方式:的更多相关文章

  1. 动态代理的两种实现方式(JDK/Cglib)

    =========================================== 原文链接: 动态代理的两种实现方式(JDK/Cglib) 转载请注明出处! ================== ...

  2. java动态代理的两种方法

    动态代理,有两种情况,第一种是有接口的情况下,你可以选择为jdk自带的动态代理的方式来编写程序,但你想要为一个实在的类编写动态代理的方式的话,这时候就必须选择一些开源的lib包,如cglib包,同时还 ...

  3. java动态代理的2种实现方式

    java的动态代理在接java的api上有说明,这里就不写了.我理解的代理: 对特定接口中特定方法的功能进行扩展,这就是代理.代理是通过代理实例关联的调用处理程序对象调用方法. 下面通过一个例子看一下 ...

  4. Java动态代理的两种实现方法

    注:文章转载自:https://blog.csdn.net/m0_38039437/article/details/77970633 一.代理的概念 动态代理技术是整个java技术中最重要的一个技术, ...

  5. Java中String对象两种赋值方式的区别

    本文修改于:https://www.zhihu.com/question/29884421/answer/113785601 前言:在java中,String有两种赋值方式,第一种是通过“字面量”赋值 ...

  6. 细说java中Map的两种迭代方式

    曾经对java中迭代方式总是迷迷糊糊的,今天总算弄懂了.特意的总结了一下.基本是算是理解透彻了. 1.再说Map之前先说下Iterator: Iterator主要用于遍历(即迭代訪问)Collecti ...

  7. 动态代理的两种方式,以及区别(静态代理、JDK与CGLIB动态代理、AOP+IoC)

    Spring学习总结(二)——静态代理.JDK与CGLIB动态代理.AOP+IoC   目录 一.为什么需要代理模式 二.静态代理 三.动态代理,使用JDK内置的Proxy实现 四.动态代理,使用cg ...

  8. Java中容器的两种初始化方式比较

    List,Set,Map的两种初始化赋值方式  List List<Integer> list2 = new ArrayList<Integer>(); for (int i= ...

  9. Java实现动态代理的两种方式

    http://m.blog.csdn.net/article/details?id=49738887

随机推荐

  1. 一整套WordPress模板制作的教程

    WordPress基本模板文件 一套完整的WordPress模板应至少具有如下文件:style.css: CSS(样式表)文件index.php : 主页模板archive.php : Archive ...

  2. Python使用split使用多个字符分隔字符串

    Python的str类有split方法,但是这个split方法只能根据指定的某个字符分隔字符串,如果要同时指定多个字符来分隔字符串,该怎么办呢? 幸运的是python的re模块中提供的split方法可 ...

  3. mongod 命令执行发现已经有进程在运行mongod数据库--errno:48 Address already in use for socket: 0.0.0.0:27017

    错误信息: listen(): bind() failed errno:48 Address already in use for socket: 0.0.0.0:27017 27017端口已经被占用 ...

  4. [troubleshoot][daily][archlinux][pacman] pacman 与 pip 包文件冲突

    今天滚系统,再次遭遇包冲突: (/) checking % error: failed to commit transaction (conflicting files) python2-reques ...

  5. SevenZip.pas BUG修改版 - 20160613

    原始版本: Henri Gourvest <hgourvest@gmail.com> 1.2版本 BUG修改: 1.对于文件名中带有空格的文件, 无法压缩, 原因是1488行, 压缩调用的 ...

  6. C#编程之委托与事件四(一)【转】

    C#编程之委托与事件(一)     本文试图在.net Framework环境下,使用C#语言来描述委托.事件的概貌.希望本文能有助于大家理解委托.事件的概念,理解委托.事件的用途,理解它的C#实现方 ...

  7. 深入Python(4):深拷贝和浅拷贝

    一.前奏:熟悉Python内存管理 在Python中,变量在第一次赋值时自动声明,在创建---也就是赋值的时候,解释器会根据语法和右侧的操作数来决定新对象的类型. 引用计数器:一个内部跟踪变量 引用计 ...

  8. myEclipse 界面窗口打不开问题

    用的myEclipse版本为2014,在其他工作空间没有此问题,在此工作有此问题. 解决办法: 把当前工作空间视图重置即可

  9. http-2.4.18 安装

    编译最新的httpd 2.4.18     编译提示apr版本低于1.4 rpm repo源是1.39的 因此编译apr 下载 apr apr-util  apr-iconv [root@ansibl ...

  10. RDIFramework.NET ━ .NET快速信息化系统开发框架 V2.7 版本发布

    历时数月,RDIFramework.NET V2.7 版本发布了,感谢大家的支持. RDIFramework.NET,基于.NET的快速信息化系统开发.整合框架,为企业或个人在.NET环境下快速开发系 ...