代理使用场景

  • 在不改变原有的代码的基础上,增加新的内容
  • Spring的AOP机制使用的动态代理实现切面编程

静态和动态代理区别

  • 根据加载被代理类的时机不同
  • 静态代理:在代码编译时确定被代理的类
  • 动态代理:在代码运行期间确定的被代理的类

静态代理

  • 首先声明接口
public interface Itest {
void test1();
void test2();
}
  • 声明接口实现类
public class TestImpl implements Itest {
@Override
public void test1() {
System.out.println("执行test1()");
}


@Override
public void test2() {
System.out.println("执行test2()");
}
}
  • 实现
public class ProxyStatic implements Itest{
private Itest itest;


public ProxyStatic(Itest itest) {
this.itest = itest;
}


public static void main(String[] args) {
Itest test = new TestImpl();
ProxyStatic proxyStatic = new ProxyStatic(test);
proxyStatic.test1();
proxyStatic.test2();
}


@Override
public void test1() {
System.out.println("test1执行开始");
itest.test1();
System.out.println("test1执行结束");
}


@Override
public void test2() {
System.out.println("test2执行开始");
itest.test2();
System.out.println("test2执行结束");
}
}

动态代理

  • 专门完成代理的操作类,是所有动态代理的父类。通过此类为一个或多个接口动态地生成实现类

eg: 我们要实现在项目中所有的方法之前和之后都加入执行开始和执行结束的提示

  • 首先声明接口
public interface Itest {
void test1();
void test2();
}
  • 声明接口实现类
public class TestImpl implements Itest {
@Override
public void test1() {
System.out.println("执行test1()");
}


@Override
public void test2() {
System.out.println("执行test2()");
}
}
  • 声明动态proxy
public class ProxyDynamic implements InvocationHandler {


// 声明被代理的对象
Object object;


public ProxyDynamic(Object object) {
this.object = object;
}


/**
*
* @param proxy
* @param method 调用的方法
* @param args
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName() + "方法执行开始");
// 执行被代理对象的指定方法
Object result = method.invoke(object, args);
System.out.println(method.getName() + "方法执行结束");
return result;
}
}
  • 实现
public class TestProxyDynamic {
public static void main(String[] args) {
Itest test = new TestImpl();
/**
* 如果一个对象想要通过proxy.newProxyInstance被代理,那么这个对象的类一定要有相应的接口
* 就像本例中的Itest接口和实现类TestImpl一样
*/
test.test1();
test.test2();
System.out.println("=============");
/**
* 执行test方法时需要加入执行开始和执行结束提示
* 打印的方法名要和调用的方法名一致
*/
InvocationHandler invocationHandler = new ProxyDynamic(test); // 传入代理对象
/**
* 参数1:代理对象的类加载器
* 参数2:被代理的对象的接口
* 参数3:代理对象
*
* 返回的值即为成功被代理的对象Object类型,需要根据情况进行强制转换
*/
Itest object = (Itest) Proxy.newProxyInstance(invocationHandler.getClass().getClassLoader(), test.getClass().getInterfaces(), invocationHandler);
object.test1();
object.test2();
}
}
  • 注意:
  • 动态代理在单个类型中无法体现出优势
  • 学习从 不停的复习开始 😃