java代理模式

 代理模式即为其余对象提供一种代理以控制对目标(真实)对象的访问,而且可在不改变目标(真实)对象状况下拓展一些额外的功能。
代理对象负责为目标(真实)对象预处理消息,过滤消息并转发消息,以及进行消息被目标(真实)对象执行后的后续处理。java

代理模式涉及的角色:

抽象角色:声明真实对象和代理对象的共同接口或抽象类;
代理角色:代理对象真实角色内部含有对真实对象的引用,从而能够操做真实对象,同时代理对象提供与真实对象相同的接口以便在任什么时候刻都能代替真实对象。同时,代理对象能够在执行真实对象操做时,附加其余的操做,至关于对真实对象进行封装。
真实角色:代理角色所表明的真实对象,是咱们最终要引用的对象。数组

1、静态代理

IUserDao.java(抽象角色:真实对象和代理对象的共同接口ide

package cn.iborder.Dao;

/**
 * 抽象角色
 * @author iborder
 */
public interface IUserDao {
	void findUsers();
}

UserDao.java(真实对象this

package cn.iborder.Dao.impl;

import cn.iborder.Dao.IUserDao;

/**
 * 真实角色
 * @author iborder
 */
public class UserDao implements IUserDao {

	@Override
	public void findUsers() {
		// TODO Auto-generated method stub
		System.out.println(this.getClass().getSimpleName()+"执行真实对象的操做");
	}
}

TestProxy.java(代理对象spa

package cn.iborder.test;

import org.junit.Test;
import cn.iborder.Dao.IUserDao;
import cn.iborder.Dao.impl.UserDao;

/**
 * 代理角色
 * @author iborder
 */
public class TestProxy implements IUserDao{
	
	IUserDao userDao;
	
	public void setUsersDao(IUserDao userDao) {
		this.userDao = userDao;
	}

	@Override
	public void findUsers() {
		// TODO Auto-generated method stub
		System.out.println(this.getClass().getSimpleName()+"代理对象附加的操做,执行前");
		if (userDao == null) {
			userDao = new UserDao();
		}
		userDao.findUsers();
		System.out.println(this.getClass().getSimpleName()+"代理对象附加的操做,执行后");
	}
	
	@Test
	public void test() {
		IUserDao userDao =  new TestProxy();
		userDao.findUsers();
	}
}

运行结果:代理

TestProxy代理对象附加的操做,执行前
UserDao执行真实对象的操做
TestProxy代理对象附加的操做,执行后

静态代理缺点:

一、真实角色必须是实现已经存在的,并将其做为代理对象的内部属性。由于代理对象须要实现与目标对象同样的接口,若是大量使用会致使类的急剧膨胀;
二、一旦接口增长方法,目标对象和代理对象都要维护。code

2、动态代理

“代理角色”将不用手动生成,而由JVM在运行时,经过指定类加载器、接口数组、调用处理程序这3个参数来动态生成。对象

Java 用于实现动态代理机制的类是java.lang.reflect.Proxy,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。 接口

使用动态代理的对象必须实现一个或多个接口。ci

Proxy方法摘要

static InvocationHandler getInvocationHandler(Object proxy)  返回指定代理实例的调用处理程序。 
static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces)  返回代理类的 java.lang.Class 对象,并向其提供类加载器和接口数组。 
static boolean isProxyClass(Class<?> class)  当且仅当指定的类经过getProxyClass方法或newProxyInstance方法动态生成为代理类时,返回 true。 
static Object newProxyInstance (ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)  返回一个指定接口的代理类实例,该接口能够将方法调用指派到指定的调用处理程序。 
static Object newProxyInstance(
	ClassLoader loader,			//定义代理类的类加载器
	Class<?>[] interfaces,		//代理类要实现的接口列表
	InvocationHandler h			//指派方法调用的调用处理程序 
)

示例:

ProxyFactory.java

package cn.iborder.factory;

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

import cn.iborder.Dao.IUserDao;
import cn.iborder.Dao.impl.UserDao;

public class ProxyFactory {
	
	private Object target;	//目标对象

	public ProxyFactory(Object target) {
		// TODO Auto-generated constructor stub
		this.target = target;
	}
	
	/*
	 * 返回代理对象
	 */
	public Object getProxyInstance() {
		return Proxy.newProxyInstance(
				target.getClass().getClassLoader(), 
				target.getClass().getInterfaces(), 
				new InvocationHandler() {
					
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						// TODO Auto-generated method stub
						System.out.println(this.getClass().getSimpleName()+"代理对象附加的操做,执行前");						
						//mehtod表明目标对象被调用的方法名
						System.out.println(method.getName());
						// 执行目标对象方法
						Object result = method.invoke(target, args);						
						System.out.println(this.getClass().getSimpleName()+"代理对象附加的操做,执行后");
						return result;
					}
				});
		}
	
	public static void main(String[] args) {
		IUserDao target = new UserDao();
		IUserDao userDao = (IUserDao) new ProxyFactory(target).getProxyInstance();
		userDao.findUsers();
	}
}

运行结果:

代理对象附加的操做,执行前
findUsers
UserDao执行真实对象的操做
代理对象附加的操做,执行后
相关文章
相关标签/搜索