java中的三种代理模式

为了搞清楚spring AOP的代理原理,在网上找了一些资料学习,总结如下:

代理模式:可以在不修改目标对象功能的前提下,对目标进行功能扩展。

1,静态代理:需要代理对象和被代理对象实现相同接口或者继承相同的父类

静态代理一个很大的问题是,一旦目标对象实现的接口或者继承的父类新增了方法,那么代理对象和目标对象都需要进行修改
 

接口:

package com.wh.www.service;

public interface DynamicProxyInterface {

	String sayHello(String name);
}

目标对象:

package com.wh.www.service.impl;

import com.wh.www.service.DynamicProxyInterface;

/**
 * 
 * @author itw_hubo
 *
 */
public class DynamicProxyService implements DynamicProxyInterface {

	public String sayHello(String name) {
		return "Hello " + name;
	}

}

代理对象factory:

package com.wh.www.service.impl;

import com.wh.www.service.DynamicProxyInterface;

public class StaticProxyService implements DynamicProxyInterface {

	private DynamicProxyInterface dynamicProxyService;
	
	public StaticProxyService(DynamicProxyInterface dynamicProxyService) {
		this.dynamicProxyService = dynamicProxyService;
	}
	
	public String sayHello(String name) {
		System.out.println("start Static Proxy demo");
		String obj = dynamicProxyService.sayHello(name);
		System.out.println("end Static Proxy demo");
		return obj;
	}

}

测试类:

package com.wh.www.service.impl;

public class StaticProxyDemo {

	public static void main(String[] args) {
		DynamicProxyService service = new DynamicProxyService();
		StaticProxyService staticproxy = new StaticProxyService(service);
		System.out.println(staticproxy.sayHello("hubo"));
	}
}

2,动态代理:利用JDK的API,动态的在内存中构建代理对象,也叫JDK代理,接口代理

要求目标对象必须实现接口,不然不能动态代理
使用上面静态代理中的接口和目标对象

动态代理factory:

package com.wh.www.service.impl;

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

/**
 * 
 * @author itw_hubo
 *
 */
public class DynamicProxyFactory {

	private Object proxyService;
	
	public DynamicProxyFactory(Object proxyService) {
		this.proxyService = proxyService;
	}
	
	public Object getProxyIntance() {
		return Proxy.newProxyInstance(proxyService.getClass().getClassLoader(), 
				proxyService.getClass().getInterfaces(), new InvocationHandler() {

					public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
						System.out.println("start Dynamic Proxy demo");
						Object rtnValue = arg1.invoke(proxyService, arg2);
						System.out.println("end Dynamic Proxy demo");
						return rtnValue;
					}
			
		});
	}
}

测试类:

package com.wh.www.service.impl;

import com.wh.www.service.DynamicProxyInterface;

/**
 * JDK的API代理
 * @author itw_hubo
 *
 */
public class DynamicProxyDemo {

	public static void main(String[] args) {
		DynamicProxyInterface proxy = new DynamicProxyService();
		DynamicProxyFactory factory = new DynamicProxyFactory(proxy);//初始化代理对象
		DynamicProxyInterface inter = (DynamicProxyInterface)factory.getProxyIntance();//获取代理对象
		System.out.println(inter.sayHello("hubo"));
	}
}

3,cglib代理,以目标对象子类的方式实现代理,因为使用的时子类,所以有几个注意点:

a,目标对象不能为final,否则报错

Exception in thread "main" java.lang.IllegalArgumentException: Cannot subclass final class com.wh.www.service.impl.CglibProxyService

b,目标对象的方法如果是final或者static,代理也不会成功,直接调用目标对象的方法,不会执行代理对象的业务方法

目标对象:


package com.wh.www.service.impl;

/**
 * @author itw_hubo
 *
 */
public class CglibProxyService {

	public String sayHello(String name) {
		return "Hello " + name;
	}
}

代理factory:


package com.wh.www.service.impl;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

/**
 * @author itw_hubo
 *
 */
public class CglibProxyFactory implements MethodInterceptor{

	//目标对象
	private Object proxy;
	
	//构造方法
	public CglibProxyFactory(Object proxy) {
		this.proxy = proxy;
	}
	
	//创建代理对象
	public Object getProxyInstance() {
		//工具类
		Enhancer en = new Enhancer();
		//设置父类
		en.setSuperclass(proxy.getClass());
		//设置回调函数
		en.setCallback(this);
		//创建子类代理对象
		return en.create();
	}
	
	public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
		System.out.println("start Cglib Proxy demo");
		Object rtnValue = arg1.invoke(proxy, arg2);
		System.out.println("end Cglib Proxy demo");
		return rtnValue;
	}

	
}

测试类:

package com.wh.www.service.impl;

/**
 * 
 * @author itw_hubo
 *
 */
public class CglibProxyDemo {

	public static void main(String[] args) {
		CglibProxyService service = new CglibProxyService();
		CglibProxyFactory factory = new CglibProxyFactory(service);
		CglibProxyService proxy = (CglibProxyService)factory.getProxyInstance();
		System.out.println(proxy.sayHello("lucy"));
	}
}

以上代码都是可以直接执行,希望能够帮助你了解代理模式。

 

------

知识使我们快乐

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值