1. 定义
Provide a surrogate or placeholder for another object to control access to it.
为其他对象提供一种代理以控制对这个对象的访问。
2. 代码
2.1 静态代理
静态代理中,代理对象和目标对象都需要实现抽象类。
抽象类:
//抽象接口供目标对象和代理对象继承
public abstract class AbstractObject {
protected abstract void doSomething();
}
目标对象:
//目标对象实现抽象类
public class RealObject extends AbstractObject {
@Override
protected void doSomething() {
System.out.println("目标对象执行了一些操作");
}
}
代理对象:
//代理对象实现抽象类
public class ProxyObject extends AbstractObject {
//要执行的实现抽象类的具体类
private AbstractObject object;
public ProxyObject(AbstractObject object) {
this.object = object;
}
@Override
protected void doSomething() {
System.out.println("代理对象执行目标对象操作前");
object.doSomething();
System.out.println("代理对象执行目标对象操作后");
}
}
测试类:
public class TestMain {
public static void main(String[] args) {
//静态代理
System.out.println("静态代理");
//传入需要代理的具体类
ProxyObject object = new ProxyObject(new RealObject());
//代理对象执行逻辑
object.doSomething();
}
}
结果:
静态代理
代理对象执行目标对象操作前
目标对象执行了一些操作
代理对象执行目标对象操作后
静态代理可以在不改变目标对象的情况下扩展功能,但是必须和目标对象实现相同的接口或抽象类,一旦接口增加方法,两者都要维护,所以可使用动态代理。
2.2 动态代理
动态该代理中,代理对象不需要实现目标对象实现的抽象类。
动态代理实现,需要用到newProxyInstance()
方法,接收三个参数。即newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
抽象类接口:
//登陆接口-目标对象要实现的接口
public interface IUserLogin {
void saveUserName();
}
目标对象:
//目标对象实现抽象接口
public class User implements IUserLogin {
@Override
public void saveUserName() {
System.out.println("用户登陆后已经保存了用户名");
}
}
动态代理对象:
//动态对象,不需要实现目标对象实现的接口
public class DynamicProxyObject {
private Object object;//目标对象
public DynamicProxyObject(Object object) {
this.object = object;
}
public Object getDynamicProxyInstance() {
return Proxy.newProxyInstance(
object.getClass().getClassLoader(),
object.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理对象执行目标对象方法前");
Object value = method.invoke(object, args);
System.out.println("代理对象执行目标对象方法后");
return value;
}
}
);
}
}
测试类:
public class TestMain {
public static void main(String[] args) {
//静态代理
System.out.println("静态代理");
//传入需要代理的具体类
ProxyObject object = new ProxyObject(new RealObject());
//代理对象执行逻辑
object.doSomething();
//动态代理
System.out.println("-------------\n动态代理");
IUserLogin user = new User();
//传入目标对象
DynamicProxyObject dynamicProxyObject = new DynamicProxyObject(user);
//调用未实现接口动态代理对象的方法,获取实现接口的代理对象
IUserLogin proxy = (IUserLogin) dynamicProxyObject.getDynamicProxyInstance();
proxy.saveUserName();//调用方法才会执行
}
}
结果:
静态代理
代理对象执行目标对象操作前
目标对象执行了一些操作
代理对象执行目标对象操作后
-------------
动态代理
代理对象执行目标对象方法前
用户登陆后已经保存了用户名
代理对象执行目标对象方法后
2.3 Cglib代理
目标对象不需要实现抽象类或接口时,可使用Cglib
代理
需要先引入Cglib的jar包
,如果报错的话,可能还需要引用asm的jar包
,点击下载
版本不对可能会出错,我使用的是cglib-2.2.2
和asm-3.3
版本的。
未实现接口的目标对象:
//没有接口实现的目标对象
public class User2 {
public void saveUserName() {
System.out.println("用户2登陆后已经保存了用户名");
}
}
内存中动态创建子类对象
public class DynamicCglibProxyObject implements MethodInterceptor{
private Object object;
//传入目标对象
public DynamicCglibProxyObject(Object object) {
this.object = object;
}
public Object getCglibProxyInstance() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(object.getClass());
//回调
enhancer.setCallback(this);
//创建代理对象返回
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
throws Throwable {
System.out.println("代理对象执行目标对象方法前");
Object value = method.invoke(object, objects);
System.out.println("代理对象执行目标对象方法后");
return value;
}
}
测试类:
public class TestMain {
public static void main(String[] args) {
//静态代理
System.out.println("静态代理");
//传入需要代理的具体类
ProxyObject object = new ProxyObject(new RealObject());
//代理对象执行逻辑
object.doSomething();
//动态代理
System.out.println("-------------\n动态代理");
IUserLogin user = new User();
//传入目标对象
DynamicProxyObject dynamicProxyObject = new DynamicProxyObject(user);
//调用未实现接口动态代理对象的方法,获取实现接口的代理对象
IUserLogin proxy = (IUserLogin) dynamicProxyObject.getDynamicProxyInstance();
proxy.saveUserName();//调用方法才会执行
//Cglib代理,目标对象没有实现接口的动态代理
System.out.println("-------------\nCglib代理");//jar包版本号需要对应,有很多错误
User2 user2 = new User2();
DynamicCglibProxyObject dynamicCglibProxyObject = new DynamicCglibProxyObject(user2);
User2 proxy2 = (User2) dynamicCglibProxyObject.getCglibProxyInstance();
proxy2.saveUserName();
}
}
结果:
静态代理
代理对象执行目标对象操作前
目标对象执行了一些操作
代理对象执行目标对象操作后
-------------
动态代理
代理对象执行目标对象方法前
用户登陆后已经保存了用户名
代理对象执行目标对象方法后
-------------
Cglib代理
代理对象执行目标对象方法前
用户2登陆后已经保存了用户名
代理对象执行目标对象方法后