一、静态代理
package com.huawei.proxy;
/**
* 静态代理。
* 0.背景:
* 我们不应该随意修改别人的代码,但是需要扩展功能时,可以用代理设计模式。
*
* 1.包括目标对象和代理对象(好比明星)和代理对象(好比经纪人)
* 2.方式:
* 2.1 目标对象继承了某个类或者实现了某接口。
* 2.2 代理对象继承了相同的父类或者实现了相同的接口。
* 2.3 代理对象中维护了一个目标对象字段。
* 2.4 在代理对象中复写或者实现相同的方法,从而起到扩展功能(例如事务)的效果。
* 3.优点:
* 3.1 不用修改目标对象代码就可以起到扩展功能的效果。
* 4.缺点:
* 4.1 目标对象和代理对象实现了相同的接口,代码上有重复。
* 4.2 一旦接口发生改变,就必须要修改目标对象和代理对象代码,非常费事。
*
* @author swh
*
*/
public class TestStaticProxy
{
public static void main(String[] args)
{
StaticTargetObj target = new StaticTargetObj();
StaticProxyObj proxyObj = new StaticProxyObj(target);
proxyObj.saveUser();
}
}
interface IUserDao
{
void saveUser();
}
class StaticTargetObj implements IUserDao
{
@Override
public void saveUser() {
System.out.println("The user has been saved.");
}
}
class StaticProxyObj implements IUserDao
{
private StaticTargetObj target;
public StaticProxyObj(StaticTargetObj target)
{
this.target = target;
}
@Override
public void saveUser()
{
System.out.println("开启事务");
target.saveUser();
System.out.println("关闭事务");
}
}
2.JDK动态代理(接口动态代理)
package com.huawei.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
*
* @author swh
*
* JDK动态代理:
* 1.背景:
* 1.1 改进静态代理的几个缺点
* 2.思路:
* 2.1 核心类:java.lang.reflect.Proxy.
* java.lang.reflect.InvocationHandler.
* 3.优点:
* 3.1 代理对象不用实现目标对象的接口了
* 3.2 利用JDK API,通过反射,在内存中动态构建代理对象
* 4.缺点:
* 4.1 目标对象必须实现接口,否则就不能使用JDK代理
*/
public class TestJDKProxy
{
public static void main(String[] args)
{
//创建目标对象
JDKTargetObj target = new JDKTargetObj();
ClassLoader classLoader = target.getClass().getClassLoader();
Class<?>[] interfaces = target.getClass().getInterfaces();
JDKProxyInvocationHandler handler = new JDKProxyInvocationHandler(target);
//创建代理对象(参数:1.目标对象类加载器 2.目标对象实现的接口 3.事件处理类)
IUserDao proxy = (IUserDao)Proxy.newProxyInstance(classLoader, interfaces, handler);
proxy.saveUser();
}
}
class JDKTargetObj implements IUserDao
{
@Override
public void saveUser()
{
System.out.println("The user has been saved.");
}
}
class JDKProxyInvocationHandler implements InvocationHandler
{
private JDKTargetObj target;
public JDKProxyInvocationHandler(JDKTargetObj target)
{
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
System.out.println("开启事务");
Object invokeRet = method.invoke(target, args);
System.out.println("关闭事务");
return invokeRet;
}
}
3.cglib动态代理 (子类动态代理)
package com.huawei.proxy;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
*
* @author swh
* 1.背景:以上两种代理都需要目标类实现接口。但是确实存在目标类未实现任何接口的情形。
* 2.思路:
* 核心包:cglib.jar以及asm.jar(或者spring-core.jar)
* 核心类: Enhancer,MethodIntercepter
* 3.优点:
* 同1.
* 4.缺点:
* 4.1 目标类CglibTargetObj不能为final类型,否则报错
* 4.2 目标类CglibTargetObj的方法如果为final/static,则不会被拦截,即只会执行目标类中的方法,
* 而不会执行额外的业务方法(比如开启关闭事务),不会有“增强”的效果。
* 原因大概是final类型的类不能被子类继承,final/static的方法也不能被子类复写。
*
*
*
*/
public class TestCglibProxy {
public static void main(String[] args) {
CglibTargetObj target = new CglibTargetObj();
CglibTargetObj proxyInstance = (CglibTargetObj)(new CglibProxyObj(target).getProxyInstance());
proxyInstance.saveUser();
}
}
/**
* 该类没有实现任何接口
* @author swh
*
*/
class CglibTargetObj
{
public void saveUser()
{
System.out.println("the user has been saved.");
}
}
class CglibProxyObj implements MethodInterceptor
{
private CglibTargetObj target;
public CglibProxyObj(CglibTargetObj target)
{
this.target = target;
}
@Override
public Object intercept(Object object, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object ret = null;
System.out.println("开启事务");
ret = method.invoke(this.target, objects);
//貌似这么写也可以
//ret = methodProxy.invoke(this.target, objects);
System.out.println("关闭事务");
return ret;
}
public Object getProxyInstance() {
Enhancer enhancer = new Enhancer();
//设置父类
enhancer.setSuperclass(this.target.getClass());
//设置回调为自身(其实MethodInterceptor就继承了CallBack接口)
enhancer.setCallback(this);
//创建代理对象
return enhancer.create();
}
}