代理模式

前言

代理模式是GOF中的一种,指的是一个类代表另一个类的功能,这种类型的设计模式属于结构型模式。代理模式在java中运用的很多,AOP就是基于动态代理实现的。代理模式又分为静态代理和动态代理。

静态代理

若代理类在程序运行前就已经存在,那么这种代理模式就是静态代理。通常情况下,静态代理类和目标类都会实现同一个接口或者派生自相同父类。

创建接口和目标实现类

package com.fzxey.proxy;

//定义目标类和代理类的接口
public interface ITestService {
	String doSome();
}
package com.fzxey.proxy.impl;

import com.fzxey.proxy.ITestService;

//实现接口
public class TestService implements ITestService {

	@Override
	public String doSome() {
		return "hello";
	}

}

代理类

package com.fzxey.proxy.impl;

import com.fzxey.proxy.ITestService;

//实现接口
public class TestProxy implements ITestService {
    //定义接口类型变量
	private ITestService target;
    //利用构造函数设置
	public TestProxy(ITestService target) {
		this.target = target;
	}
	@Override
	public String doSome() {
        //增强目标类中的方法
		return target.doSome().toUpperCase();
	}

}

测试类

package com.fzxey.proxy;


import org.junit.Test;

import com.fzxey.proxy.impl.TestProxy;
import com.fzxey.proxy.impl.TestService;

public class ProxyTest {

	@Test
	public void test() {
		ITestService ts = new TestService();
		TestProxy tp = new TestProxy(ts);
		System.out.println(tp.doSome());
	}

}

结果

HELLO

动态代理

代理类在程序运行时创建的代理方式被成为 动态代理。 也就是说,这种情况下,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。

这里介绍两种动态代理方式:JDK动态代理(java自带的)和CGLIB动态代理(github开源项目)

JDK动态代理

java.lang.reflect.Proxy:生成动态代理类和对象;
java.lang.reflect.InvocationHandler(处理器接口):可以通过invoke方法实现
对真实角色的代理访问。
每次通过 Proxy 生成的代理类对象都要指定对应的处理器对象。

创建接口和目标实现类

package com.fzxey.proxy;

//定义目标类和代理类的接口
public interface ITestService {
	String doSome();
}
package com.fzxey.proxy.impl;

import com.fzxey.proxy.ITestService;

//实现接口
public class TestService implements ITestService {

	@Override
	public String doSome() {
		return "hello";
	}

}

JDK代理实现

package com.fzxey.proxy;


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

import org.junit.Test;

import com.fzxey.proxy.impl.TestProxy;
import com.fzxey.proxy.impl.TestService;

public class ProxyTest {

	@Test
	//JDK动态代理测试
	public void test1() {
		//获取目标类对象
		ITestService ts = new TestService();
		//获取动态代理对象
		ITestService its = (ITestService)Proxy.newProxyInstance(
				//目标类的类加载器
				ts.getClass().getClassLoader()
				//目标类的实现的所有的接口
				, ts.getClass().getInterfaces()
				//处理器
				, new InvocationHandler() {
					/**
					 * proxy:代理对象
					 * method:目标的方法对象
					 * args:目标方法的参数
					 */
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						String msg = (String)method.invoke(ts, args);
						return msg.toUpperCase();
					}
		});
		System.out.println(its.doSome());
	}

}

结果

HELLO
CGLIB动态代理

Cglib 动态代理是针对代理的类, 动态生成一个子类, 然后子类覆盖代理类中的方法, 如果是private或是final类修饰的方法,则不会被重写。
CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,CGLIB是一个好的选择。
CGLIB作为一个开源项目,其代码托管在github,地址为:https://github.com/cglib/cglib

创建目标类

package com.fzxey.proxy.impl;

public class TestService implements ITestService {

	@Override
	public String doSome() {
		return "hello";
	}

}

CGLIB代理类

package com.fzxey.proxy;

import java.lang.reflect.Method;

import com.fzxey.proxy.impl.TestService;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor{
	private TestService target;
	public CglibProxy(TestService target) {
		this.target = target;
	}
	/**
	 * 创建cglib代理对象的方法
	 * @return
	 */
	public TestService createProxy() {
		//创建增强器
		Enhancer e = new Enhancer();
		//指定父类
		e.setSuperclass(TestService.class);
		//指定回调接口对象
		e.setCallback(this);
		//创建cglib代理对象
		return (TestService) e.create();
		
	}
	/**
	 * 拦截方法
	 */
	@Override
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
		// TODO Auto-generated method stub
		String msg = (String) method.invoke(target, args);
		return msg.toUpperCase();
	}

}

测试

package com.fzxey.proxy;


import org.junit.Test;

import com.fzxey.proxy.impl.TestProxy;
import com.fzxey.proxy.impl.TestService;

public class ProxyTest {

	@Test
	public void test3() {
		TestService ts = new TestService();
		TestService cp = new CglibProxy(ts).createProxy();
		System.out.println(cp.doSome());
		
	}
	
}

结果

HELLO

@Fzxey

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值