动态代理模式

上一篇我们学习了静态代理

静态代理有不足:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护.

例如在上一篇的基础上我们又新增了一个学生模块,代码如下

接口:IStudentDao.java

/** 
 * 接口 
 */  
public interface IStudentDao {  
  
    void save();  
}  

目标类:StudentDaoImpl.java

/** 
 * 接口实现 
 * 目标类
 */  
public class StudentDaoImpl implements IStudentDao {  
    public void save() {  
        System.out.println("----已经保存学生数据!----");  
    }  
}

代理类:StudentDaoProxy.java

/** 
 * 代理类,静态代理 
 */  
public class StudentDaoProxy implements IStudentDao{  
    //接收保存目标对象  
    private IStudentDao target;  
    public StudentDaoProxy(IStudentDao target){  
        this.target=target;  
    }  
  
    public void save() {  
        System.out.println("开始事务...");  
        target.save();//执行目标对象的方法  
        System.out.println("提交事务...");  
    }  
}  


测试类:TestProxy.java

/** 
 * 测试类 
 */  
public class TestProxy2 {  
    public static void main(String[] args) {  
        //目标对象  
        IStudentDao target = new StudentDaoImpl();  
  
        //代理对象,把目标对象传给代理对象,建立代理关系  
        StudentDaoProxy proxy = new StudentDaoProxy(target);  
  
        proxy.save();//执行的是代理的方法  
    }  
}  

如果还要有教师类,我们又要写一遍代理类,是不是很烦琐?

ok,救世主动态代理来了!

     代理类在程序运行时创建的代理方式被成为动态代理。 我们上面静态代理的例子中,代理类(StudentDaoProxy)是自己定义好的,在程序运行之前就已经编译完成。然而动态代理,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。

代码示例:

用户接口
package com.hzrj.proxy;

public interface IUserDao {
	 void save();
}

实现类
package com.hzrj.proxy;

public class UserDaoImpl implements IUserDao{
	@Override
	public void save() {
		System.out.println("----已经保存用户数据!----"); 
	}
}

-----------------------
学生接口
package com.hzrj.proxy;

public interface IStudentDao {
	void save();
}

实现类
package com.hzrj.proxy;

public class StudentDaoImpl implements IStudentDao{
	@Override
	public void save() {
		System.out.println("----已经保存学生数据!----"); 
	}
}

--------------------------
动态代理核心类
package com.hzrj.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocationHandler<T> implements InvocationHandler  {
	private T target;
	public MyInvocationHandler(T target) {
		this.target=target;
	}
	/**
     * proxy:代表动态代理对象
     * method:代表正在执行的方法
     * args:代表调用目标方法时传入的实参
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理执行" +method.getName() + "方法");
        //代理过程中插入监测方法,计算该方法耗时
        System.out.println("事务开始...");
        Object result = method.invoke(target, args);
        System.out.println("事务提交...");
        return result;
    }
}
---------------------------
测试类
package com.hzrj.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class ProxyTest {
	public static void main(String[] args) {
		//创建一个实例对象,这个对象是被代理的对象
		IUserDao userDao=new UserDaoImpl();
		//创建一个与代理对象相关联的InvocationHandler
		InvocationHandler myHandle=new MyInvocationHandler<IUserDao>(userDao);
		//创建一个代理对象myProxy来代理userDao,代理对象的每个执行方法都会替换执行MyInvocationHandler中的invoke方法
		IUserDao userProxy = (IUserDao)Proxy.newProxyInstance(IUserDao.class.getClassLoader(), 
				new Class<?>[]{IUserDao.class}, myHandle);

       //代理执行保存数据的方法
		userProxy.save();
	}
}

运行结果:

代理执行save方法
事务开始...
----已经保存用户数据!----
事务提交...

测试类2
package com.hzrj.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class ProxyTest2 {
	public static void main(String[] args) {
		//创建一个实例对象,这个对象是被代理的对象
		IStudentDao stuDao=new StudentDaoImpl();
		//创建一个与代理对象相关联的InvocationHandler
		InvocationHandler myHandle=new MyInvocationHandler<IStudentDao>(stuDao);
		//创建一个代理对象myProxy来代理userDao,代理对象的每个执行方法都会替换执行MyInvocationHandler中的invoke方法
		IStudentDao stuProxy = (IStudentDao)Proxy.newProxyInstance(IStudentDao.class.getClassLoader(), 
				new Class<?>[]{IStudentDao.class}, myHandle);

       //代理执行保存数据的方法
		stuProxy.save();
	}
}

运行结果:
代理执行save方法
事务开始...
----已经保存学生数据!----
事务提交...
在代理过程中,我们在真正执行被代理对象的方法前后都会加入自己其他处理代码,比方说日志记录,时间记录,事务处理等等。这也是Spring中的AOP实现的主要原理!!!!


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

御前两把刀刀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值