Java代理

代理模式:

代理模式是常用的java设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象和一个委托类的对象关联,代理类的对象本身并不是真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。


按照代理的创建时期,代理类可以分为两种:

静态代理:创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了

动态代理:在程序运行时,运用反射机制动态创建而成。


公共接口:

package com.learns.proxy;

public interface Count {
	
	// 查看帐号方法
	public void queryCount();
	
	// 修改帐号方法
	public void updateCount();
	
}
接口实现类:

package com.learns.proxy;

public class CountImpl implements Count {

	public void queryCount()
	{
		System.out.println("查看账户方法");
	}
	
	public void updateCount()
	{
		System.out.println("修改账户方法");
	}
	
}

一、静态代理

package com.learns.proxy;

public class CountProxy implements Count {

	private CountImpl countImpl;
	
	public CountProxy(CountImpl countImpl)
	{
		this.countImpl = countImpl;
	}
	
	public void queryCount()
	{
		System.out.println("查询处理之前");
		countImpl.queryCount();
		System.out.println("查询处理之后");
	}
	
	public void updateCount()
	{
		System.out.println("修改处理之前");
		countImpl.updateCount();
		System.out.println("修改处理之后");
	}
	
}
测试类:

package com.learns.proxy;

public class TestCount {
	public static void main(String[] args) {
		CountImpl countImpl = new CountImpl();
		CountProxy countProxy = new CountProxy(countImpl);
		countProxy.updateCount();
		countProxy.queryCount();
	}
}
二、JDK动态代理

JDK动态代理使用到一个Proxy类和一个InvocationHandler接口。Proxy仅支持interface代理(也就是代理类必须实现接口)

InvocationHandler接口:
public interface InvocationHandler {
           public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;
}
参数说明:
Object proxy:指被代理的对象。
Method method:要调用的方法
Object[] args:方法调用时所需要的参数

Proxy类:
Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,此类提供了如下的操作方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)  throws IllegalArgumentException
参数说明:
ClassLoader loader:类加载器
Class<?>[] interfaces:得到全部的接口
InvocationHandler h:得到InvocationHandler接口的子类实例

package com.learns.proxy.jdk;

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

public class CountProxyFactory implements InvocationHandler {
	
	private Object target;
	
	public Object bind(Object target)
	{
		this.target = target;
		return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
	}
	
	public Object invoke(Object proxy,Method method,Object[] args) throws Throwable
	{
		boolean objFlag = method.getDeclaringClass().getName().equals("java.lang.Object");
		
		Object result = null;
		if(!objFlag)
		{
			System.out.println("代理before");
		}
		result = method.invoke(this.target, args);
		if(!objFlag)
		{
			System.out.println("代理after");
		}
		return result;
	}
}
测试类:

package com.learns.proxy.jdk;

import com.learns.proxy.Count;
import com.learns.proxy.CountImpl;

public class CountProxyTest {

	public static void main(String[] args)
	{
		// 下面使用JDK的代理类,一个代理可以代理很多接口
		Count count = (Count)new CountProxyFactory().bind(new CountImpl());
		System.out.println(count);
		count.queryCount();
	}
}
三、CGLIB动态代理

针对JDK仅支持实现接口的委托类进行代理的缺陷,CGLIB解决了这个问题。 使其委托类也可是非接口实现类。

CGLIB内部使用到ASM,所以需要引入asm-3.3.jar、cglib-2.2.2.jar

注意:cglib版本为3.0或3.1,asm版本为3.1时。版本冲突,报错java.lang.IncompatibleClassChangeError: class net.sf.cglib.core.DebuggingClassWriter has interface org.objectweb.asm.ClassVisitor as super class。使用cglib2.2可解决此问题,该版本中的DebuggingClassWriter的父类为ClassWriter


非接口实现类:

package com.learns.proxy.cglib;

public class Person {
	
	public void show()
	{
		System.out.println("showing");
	}
}
代理类:

package com.learns.proxy.cglib;

import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CountCglibProxyFactory implements MethodInterceptor {

	private Object target;
	
	public Object getInstance(Object target)
	{
		this.target = target;
		return Enhancer.create(this.target.getClass(), this);
	}
	
	public Object intercept(Object obj,Method method,Object[] args,MethodProxy methodProxy) throws Throwable
	{
		boolean objFlag = method.getDeclaringClass().getName().equals("java.lang.Object");
		if(!objFlag)
		{
			System.out.println("before");
		}
		Object result = null;
		result = methodProxy.invokeSuper(obj, args);
		if(!objFlag)
		{
			System.out.println("after");
		}
		return result;
	}
}
测试类:

package com.learns.proxy.cglib;

import com.learns.proxy.Count;
import com.learns.proxy.CountImpl;

public class CountCglibProxyTest {

	public static void main(String[] args) {
		Count count = (Count)new CountCglibProxyFactory().getInstance(new CountImpl());
		count.updateCount();
		
		Person person = (Person)new CountCglibProxyFactory().getInstance(new Person());
		System.out.println(person);
		person.show();
	}
}

参考文章:

http://blog.csdn.net/yuanlaishinizhu/article/details/12998847

http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html


  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java代理模式是一种结构型设计模式,其目的是为其他对象提供一种代理以控制对这个对象的访问。代理对象可以在客户端和目标对象之间充当中介,以便于客户端访问目标对象时,可以在不改变目标对象的情况下添加一些额外的功能,比如安全性、远程访问、缓存等。 在Java中,代理模式可以通过两种方式实现:静态代理动态代理静态代理需要手动编写代理类,而动态代理可以在运行时通过反射机制动态生成代理类,更加灵活。 举个例子,假设我们有一个接口`Subject`,其中定义了一些方法。我们希望在调用这些方法时,增加一些额外的日志记录功能。我们可以编写一个代理类`SubjectProxy`,在代理类中实现接口方法并调用目标对象的方法,同时在方法前后添加日志记录的代码。客户端则通过代理类访问目标对象。 静态代理示例代码如下: ```java public interface Subject { void doSomething(); } public class RealSubject implements Subject { @Override public void doSomething() { System.out.println("RealSubject do something."); } } public class SubjectProxy implements Subject { private Subject realSubject; public SubjectProxy(Subject realSubject) { this.realSubject = realSubject; } @Override public void doSomething() { System.out.println("Before do something."); realSubject.doSomething(); System.out.println("After do something."); } } public class Client { public static void main(String[] args) { Subject realSubject = new RealSubject(); Subject subjectProxy = new SubjectProxy(realSubject); subjectProxy.doSomething(); } } ``` 动态代理示例代码如下: ```java public class SubjectHandler implements InvocationHandler { private Object target; public SubjectHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Before " + method.getName()); Object result = method.invoke(target, args); System.out.println("After " + method.getName()); return result; } } public class Client { public static void main(String[] args) { Subject realSubject = new RealSubject(); InvocationHandler handler = new SubjectHandler(realSubject); Subject subjectProxy = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler); subjectProxy.doSomething(); } } ``` 无论是静态代理还是动态代理代理模式都可以在不改变目标对象的情况下,为其添加额外的功能,提高代码的可复用性和灵活性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值