代理模式是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个真实对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。

1、静态代理

静态代理:由程序员创建或特定工具自动生成源代码,也就是在编译时就已经将接口,被代理类,代理类等确定下来。在程序运行之前,代理类的.class文件就已经生成。

静态代理通常用于对原有业务逻辑的扩充。比如持有二方包的某个类,并调用了其中的某些方法。然后出于某种原因,比如记录日志、打印方法执行时间,但是又不好将这些逻辑写入二方包的方法里。所以可以创建一个代理类实现和二方方法相同的方法,通过让代理类持有真实对象,然后在原代码中调用代理类方法,来达到添加我们需要业务逻辑的目的。

这其实也就是代理模式的一种实现,通过对真实对象的封装,来实现扩展性。

一个典型的代理模式通常有三个角色,这里称之为**代理三要素**

共同接口

package com.ken.staticproxy;

public interface Person {
	 void giveMoney();
	 }

  

真实对象

package com.ken.staticproxy;

public class Student implements Person {

    private String name;
    public Student(String name) {
        this.name = name;
    }
	@Override
	public void giveMoney() {
		// TODO Auto-generated method stub
		System.out.println(name + "上交班费50元");
	}

}

  

代理对象

package com.ken.staticproxy;

public class StudentProxy implements Person {

	Student stu;
    
    public StudentProxy(Person stu) {
        // 只代理学生对象
        if(stu.getClass() == Student.class) {
            this.stu = (Student)stu;
        }
    }
	@Override
	public void giveMoney() {
		// TODO Auto-generated method stub
		System.out.println("this is proxy start!");
		stu.giveMoney();
		System.out.println("this is proxy end!");
	}

}

  测试

package com.ken.staticproxy;

public class Test {

	public static void main(String[] args) {
		Person person = new Student("test");
		person.giveMoney();
		
		System.out.println("-------------------------");
		Person  proxy = new StudentProxy(person);
		proxy.giveMoney();
	}
}

  输出结果

test上交班费50元
-------------------------
this is proxy start!
test上交班费50元
this is proxy end!

静态代理的优点和缺点

先看看代理模式的优点: 扩展原功能,不侵入原代码。

再看看这种代理模式的缺点:如果需要扩展的扩展的功能模块太多则需要增加更多的方法

2、动态代理

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

动态代理实现

使用动态代理,需要将要扩展的功能写在一个InvocationHandler 实现类里:

这个Handler中的invoke方法中实现了代理类要扩展的公共功能。

public class StudentProxy implements InvocationHandler{
    
	private Object realObject;

    public StudentProxy(Object realObject) {
        this.realObject = realObject;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //代理扩展逻辑
        System.out.println("this is proxy start!");
       Object object =  method.invoke(realObject, args);
       System.out.println("this is proxy end!");
        return object;
    }
}

  

  测试

Proxy.newProxyInstance 传入的是一个ClassLoader, 一个代理接口,和我们定义的handler,返回的是一个Proxy的实例。

import java.lang.reflect.Proxy;

public class Test {

	public static void main(String[] args) {
		Person person = new Student("test");
		person.giveMoney();
		
		System.out.println("-------------------------");
		Person proxy = (Person) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Person.class}, new StudentProxy(person)); 
		proxy.giveMoney();
		
	}
}

  

  输出结果

test上交班费50元
-------------------------
this is proxy start!
test上交班费50元
this is proxy end!

  

posted on 2018-04-01 23:49  ken--!  阅读(129)  评论(0编辑  收藏  举报