代理模式:为其他对象提供一个代理,以控制对某个对象的访问。
比如有对象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
保存用户!
提交事务
------------------------------
查找用户