设计模式之动态代理模式

代理模式:为其他对象提供一个代理,以控制对某个对象的访问。

比如有对象A和B,我们不想让A直接访问B,而是提供一个代理,让代理控制A对B的访问。

代理模式有一个缺陷,如果我们想让每个对象都拥有一个代理,则需要编写多个代理,这让人很蛋痛,因此我们引入动态代理模式。

JAVA对动态代理模式有着几乎完美的支持,Spring就是使用JAVA中的动态代理模式来管理声明式事务的,下面将会模拟动态代理在事务管理中的使用,来介绍动态代理模式的使用方法。

Java实现动态代理模式有两种方法:

1、实现接口InvocationHandler

package com.proxy;

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

public class DynamicProxy implements InvocationHandler {
	
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object result = null;
		if (method.getName().startsWith("save")) {
			System.out.println("开启事务");
			System.out.println("开始执行方法:"+method.getName());
			try {
				result = method.invoke(proxy, args);
				System.out.println("提交事务");
			} catch (Exception e) {
				System.out.println("事务回滚");
			}
			System.out.println("------------------------------");
		} else if (method.getName().startsWith("query")) {
			System.out.println("开始执行方法:"+method.getName());
			result = method.invoke(proxy, args);
		}
		
		return result;
	}

	public static void main(String[] args) {
		DynamicProxy proxy = new DynamicProxy();
		UserService userService = new UserServiceImpl();
		Method[] methods = userService.getClass().getMethods();
		for (Method method : methods) {
			try {
				proxy.invoke(userService, method, new Object[]{});
			} catch (Throwable e) {
				e.printStackTrace();
			}
		}
	}

}

package com.proxy;

public interface UserService {
	
	public void saveUser();
	
	public void queryUser();
	
}

package com.proxy;

public class UserServiceImpl implements UserService {

	public void saveUser() {
		System.out.println("保存用户!");
	}

	public void queryUser() {
		System.out.println("查找用户");
	}

}

程序运行的结果:

开启事务
开始执行方法:saveUser
保存用户!
提交事务
------------------------------
开始执行方法:queryUser
查找用户

通过以上的例子我们可以看到,动态代理模式只需要生成一个代理则可,这个代理只需要实现接口InvocationHandler,这个代理跟具体的业务对象并不会耦合在一起,通过动态代理,我们可以很方便的为某些方法添加日志或者事务,而不会增加业务对象的复杂度,这也是AOP(面向切面编程)的思想。

 

2、使用cglib

cglib概述:
cglib(Code Generation Library)是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。
cglib封装了asm,可以在运行期动态生成新的class。
cglib用于AOP,jdk中的proxy必须基于接口,cglib却没有这个限制。

以下用一个例子来说明cglib的使用方法。

1) 模拟为Service中的方法添加事务。

public interface UserService {
	
	public void saveUser();
	
	public void queryUser();
	
}
public class UserServiceImpl implements UserService {

	public void saveUser() {
		System.out.println("保存用户!");
	}

	public void queryUser() {
		System.out.println("查找用户");
	}

}


2) 首先实现接口MethodInterceptor,建立方法拦截器。

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

public class CglibMethodInterceptor implements MethodInterceptor {

	public Object intercept(Object object, Method method, Object[] args,
			MethodProxy methodProxy) throws Throwable {
			Object result = null;
			System.out.println("开启事务");
			System.out.println("开始执行方法:"+method.getName());
			try {
				result = methodProxy.invokeSuper(object, args);
				System.out.println("提交事务");
			} catch (Exception e) {
				System.out.println("事务回滚");
			}
			System.out.println("------------------------------");
			
		return result;
	}
}


2) 实现接口CallbackFilter,建立方法过滤器。只对以save开头的方法添加事务.

import java.lang.reflect.Method;
import net.sf.cglib.proxy.CallbackFilter;

public class MethodFilter implements CallbackFilter {

	public int accept(Method method) {
		if (method.getName().startsWith("save")) {
			return 0;
		}
		
		return 1;
	}
}


3) 调用cglib

import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.NoOp;
import com.proxy.UserServiceImpl;

public class CglibExample {
	
	public static void main(String[] args){
		Enhancer enhancer=new Enhancer();  
		enhancer.setSuperclass(UserServiceImpl.class);  
		enhancer.setCallbacks(new Callback[]{new CglibMethodInterceptor(), NoOp.INSTANCE});
		enhancer.setCallbackFilter(new MethodFilter());
		UserServiceImpl userService = (UserServiceImpl) enhancer.create();
		userService.saveUser();
		userService.queryUser();
	}
}


4) 程序的执行结果

开启事务
开始执行方法:saveUser
保存用户!
提交事务
------------------------------
查找用户

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值