浅谈java代理—代理模式

        1. 什么是代理 & 为什么使用代理

        举个例子:小明的朋友去外地旅游,然后小明托朋友买一些当地的特产。此处小明的朋友则可以视为是代理。从案例来看,小明想买外地的东西,但他办不到,他发出买的动作,但实际买东西的是小明的朋友。

        就好比在代码中想要增加一些功能,比如性能监测,而如果修改代码则违反了开闭原则,也可能会带来一系列问题。

        于是我们可以创建一个代理类去增强我们原来类的功能,但具体的实现还是由原类负责,代理类只负责新增功能

UML类图:

    

        2. 怎么使用代理

               静态代理:

        每次创建代理类都需要人为的实现某个接口,或者以匿名内部类的形式,当类方法很多的时候没个方法都要重写,一来降低工作效率,二来可能会漏那么一两个方法。

               动态代理:

        jdk动态代理,代码如下

public interface ProxyInterface {
	void work();
}


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

import com.lastsummer.proxydao.ProxyInterface;

public class JdkProxyConcreteClass implements ProxyInterface {

	@Override
	public void work() {
		System.out.println("开始工作");
		
	}
	
	private Object jdkProxy(Object bean) {
		//产生代理对象  需强转
		Object obj = Proxy.newProxyInstance(
				JdkProxyConcreteClass.class.getClassLoader(),   //一般为当前类的类加载器
				bean.getClass().getInterfaces(),		//具体类所实现的接口
				new InvocationHandler() {				//自定义执行处理器
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						System.out.println("记录执行前毫秒数");
						Object obj = method.invoke(bean, args);  //源方法调用
						System.out.println("记录执行后毫秒数");
						return obj;
					}
				});
		return obj;
	}
	
	public static void main(String[] args) {
		JdkProxyConcreteClass obj = new JdkProxyConcreteClass();
		ProxyInterface proxy = (ProxyInterface) obj.jdkProxy(obj);
		
		proxy.work();
//		记录执行前毫秒数
//		开始工作
//		记录执行后毫秒数
	}
	
}

        这种方法的缺点是只能在有接口的时候使用

        cglib动态代理,代码如下(必须导入cglib.jar 和 asm.jar)

public class ProxyClass {
	public void work() {
		System.out.println("开始工作");
	}
}


import java.lang.reflect.Method;

import com.lastsummer.proxydao.ProxyClass;

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

public class CglibProxyConcreteClass {
	private Object cglibProxy(Object bean) {
		Enhancer enhancer = new Enhancer();
		//设置父类
		enhancer.setSuperclass(ProxyClass.class);
		//设置自定义处理器
		enhancer.setCallback(new MethodInterceptor() {
			
			@Override
			public Object intercept(Object proxy, Method method, Object[] args, MethodProxy arg3) throws Throwable {
				System.out.println("记录执行前毫秒数");
				//原对象方法执行
				Object obj = method.invoke(bean, args);
				System.out.println("记录执行后毫秒数");
				return obj;
			}
		});
		return enhancer.create();
	}
	
	public static void main(String[] args) {
		CglibProxyConcreteClass obj = new CglibProxyConcreteClass();
		ProxyClass proxy = (ProxyClass) obj.cglibProxy(new ProxyClass());
		
		proxy.work();
//		记录执行前毫秒数
//		开始工作
//		记录执行后毫秒数

	}
	
}


       种方法在对类产生代理时父类或者父类中的方法不能是final的,如果是就会抛异常。(如果你要问为什么jdk动态代理没问题,那是因为接口上或者接口的方法不能被final修饰)。

       3. 代理的使用

       就像上面一样,我们可以在不修改之前的代码,而且在之前代码的基础上增加新的功能。最典型的思想就是aop(面向切面)。为什么叫切面,我们可以把之前的代码当成汉堡包,然后切面就是把汉堡包切开,然后在切面中加入想加的东西。
Spring事务就是基于aop,在方法执行前开启事务,方法执行后(回滚/提交)事务。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值