Java动态代理和静态代理模式
什么是动态代理?
现实生活中火车票代理售后点:买票,退票,代理点购票。购买方式有直接到火车站售票点购买,或者去火车票代售点购买火车票。
此时,代售点就是代理中介(具有购买,和退票)。
画图理解
举个例子:假设火车站有购买车票方法和退票的方法,代理售票点也有购买车票和退票方法。
动态代理-实现代理购买火车票
- 创建火车站购买车票接口
/**
* 火车票购买窗口
* @author jkl
*
*/
public interface ChooseService {
//购买火车票
public void buyTicket(String name);
//退火车票窗口
public void exitTicket(String name);
}
- 创建火车站购买车票实现接口类(委托类)
public class ChooseServiceImpl implements ChooseService{
@Override
public void buyTicket(String name) {
System.out.println("通过---["+name+"]---购买了车票");
}
@Override
public void exitTicket(String name) {
System.out.println("通过---【"+name+"---】退了车票");
}
}
- 创建jdk动态代理类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* jdk动态代理类对象
* @author jkl
*
*/
public class MyChooseProxyHandler implements InvocationHandler{
private Object target ;
//设置代理接口类
public void setInterface(Object target){
this.target=target;
}
//获取被代理类对象
public Object getProxy(Object target){
//System.out.println("使用当前类的ChooseService:"+this.getClass().getClassLoader());
//System.out.println("当前类对象的接口ChooseService:"+target.getClass().getInterfaces());
//System.out.println("当前类对象MyChooseProxyHandler:"+this);
Object result = Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
return result;
}
/**
* proxy : 代理对象
* methode:代理方法
* args: 代理参数
* 处理代理实例并返回结果
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result= method.invoke(target, args);
logs(method.getName());
return result;
}
/**
* 日志记录方法处理
*/
public void logs(String method){
System.out.println("操作日志记录了"+method+"方法");
}
}
- 测试jdk动态代理
public class ChooseController {
public static void main(String[] args) {
ChooseService choose = new ChooseServiceImpl();
choose.buyTicket("火车站");
MyChooseProxyHandler handler = new MyChooseProxyHandler();
handler.setInterface(choose);
ChooseService service = (ChooseService) handler.getProxy(choose);
service.buyTicket("代理售后点");
service.exitTicket("代理售后点");
}
}
- 输出结果:
通过---[火车站]---购买了车票
通过---[代理售后点]---购买了车票
操作日志记录了buyTicket方法
通过---【代理售后点---】退了车票
操作日志记录了exitTicket方法
静态代理-实现案例
- 创建用户接口类
package com.urun.proxy.users;
public interface UserService {
public void add(String name);
public void update(String id);
public void delete(String id);
public void getAll();
}
- 创建用户接口实现类
package com.urun.proxy.users;
public class UserServiceImpl implements UserService {
@Override
public void add(String name) {
System.out.println(name+"新增用户信息");
}
@Override
public void update(String id) {
System.out.println("编辑用户信息");
}
@Override
public void delete(String id) {
System.out.println("删除用户信息");
}
@Override
public void getAll() {
System.out.println("查询所有用户信息");
}
}
- 创建静态代理类
package com.urun.proxy.users;
/**
* 静态代理
* @author jkl
*
*/
public class UserServiceProxy implements UserService{
private UserServiceImpl userService;
public void setUserService(UserServiceImpl userService) {
this.userService = userService;
}
@Override
public void add(String name) {
userService.add(name);
this.logs("add");
}
@Override
public void update(String id) {
userService.update(id);
this.logs("update");
}
@Override
public void delete(String id) {
userService.delete(id);
this.logs("delete");
}
@Override
public void getAll() {
userService.getAll();
this.logs("getAll");
}
public void logs(String msg){
System.out.println("扩展业务:操作日志"+msg);
}
}
- 测试静态代理
package com.urun.proxy.users;
public class UserClient {
public static void main(String[] args) {
UserServiceImpl userService = new UserServiceImpl();
UserServiceProxy proxy = new UserServiceProxy();
proxy.setUserService(userService);
proxy.add("静态代理:");
proxy.delete("001");
}
}
输出结果:
静态代理:新增用户信息
扩展业务:操作日志add
删除用户信息
扩展业务:操作日志delete
Java动态代理源码分析
InvocationHandler接口类
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
invoke方法
@CallerSensitive
public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
MethodAccessor ma = methodAccessor; // read volatile
if (ma == null) {
ma = acquireMethodAccessor();
}
return ma.invoke(obj, args);
}
Proxy接口类
//生成得到代理类
public Object getProxy(){
Object object = Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
return object;
}
newProxyInstance方法源码
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
总结分析动态代理和静态代理的区别?
1.动态代理实现原理
动态代理基于Java反射机制完成,静态代理通过类实现注入依赖完成。
2.优缺点:
2.1.动态代理只能实现类已经实现的接口代理,不能对类直接代理,可以接口任意一个方法
扩展和操作,不需要全部实现接口的所有方法。
2.1.静态代理的类需要实现全部被代理的接口类的方法,对于不需要扩展的方法造成代码冗
3.代理的流程:
代理的四要素:代理对象、被代理的行为、被代理的对象、行为的完全控制