什么是代理模式

目标对象不可访问,通过代理对象增强功能访问。

生活中:
美国学校 ===>目标对象
中介 ===>代理对象
家长 ===>客户端对象

静态代理

什么是静态代理
它是代理模式的一种.
它具备以下特点:
1)目标对象和代理对象实现同一个业务接口
2)目标对象必须实现接口
3)代理对象在程序运行前就已经存在
4)能够灵活的进行目标对象的切换,却无法进行功能的灵活处理(使用动态代理解决此问题)

静态代码流程
image.png
代码实现

接口

  1. /*
  2. 业务接口,规定业务功能。
  3. */
  4. public interface Service {
  5. void sing();
  6. }

目标对象

  1. /*
  2. 目标对象刘德华,规定业务功能。
  3. */
  4. public class SuperStatLiu implements Service {
  5. public void sing() {
  6. System.out.println("我是刘德华,正在唱歌...");
  7. }
  8. }
  1. /*
  2. 目标对象周杰伦,规定业务功能。
  3. */
  4. public class SuperStarZhou implements Service {
  5. @Override
  6. public void sing() {
  7. System.out.println("我是周杰伦,正在唱歌....");
  8. }
  9. }

代理对象

  1. public class Agent implements Service {
  2. private Service target;
  3. public Agent(Service target){
  4. this.target=target;
  5. }
  6. public void sing() {
  7. System.out.println("预定时间");
  8. System.out.println("预定场地");
  9. target.sing();
  10. System.out.println("结算费用");
  11. }
  12. }

我们

  1. public class MyTest {
  2. @Test
  3. public void testAgent(){
  4. Service agent = new Agent(new SuperStarZhou());
  5. agent.sing();
  6. }
  7. }

JDK动态代理

image.png

JDK动态代理
1)目标对象必须实现业务接口
2)JDK代理对象不需要实现业务接口
3)JDK动态代理的对象在程序运行前不存在.在程序运行时动态的在内存中构建
4)JDK动态代理灵活的进行业务功能的切换
5)本类中的方法(非接口中的方法)不能被代理

JDK动态代理用到的类和接口
它是使用现成的工具类完成JDK动态实现.
1)Proxy类
它是java.lang.reflect.Proxy包下的类. 它有一个方法Proxy.newProxyInstance(…..)专门用来生成动态代理对象.
public static Object newProxyInstance(ClassLoader loader, //类加载器
Class<?>[] interfaces,//目标对象实现的所有接口
InvocationHandler h //它就类似于Agent的功能,代理的功能和目标对象的业务功能调用在这
)
throws IllegalArgumentException
{…}

2)Method类
反射用的类,用来进行目标对象的方法的反射调用.
method对象接住我们正在调用的方法sing(),show()
method==sing(),show()
method.invoke();==>手工调用目标方法 sing(); show();

3)InvocationHandler接口
它是实现代理和业务功能的.我们在调用时使用匿名内部实现.

代码实现
接口

  1. /*
  2. 业务接口
  3. */
  4. public interface Service {
  5. void sing();
  6. String show(int age);
  7. }

目标对象

  1. /*
  2. 目标对象刘德华
  3. */
  4. public class SuperStarLiu implements Service {
  5. @Override
  6. public void sing() {
  7. System.out.println("我是刘德华,我正在表演唱歌....");
  8. }
  9. @Override
  10. public String show(int age) {
  11. System.out.println("刘德华的show...."+age);
  12. return "liu";
  13. }
  14. }
  1. /*
  2. 目标对象周杰伦
  3. */
  4. public class SuperStarZhou implements Service {
  5. @Override
  6. public void sing() {
  7. System.out.println("我是周杰伦,我正在表演唱歌");
  8. }
  9. @Override
  10. public String show(int age) {
  11. System.out.println("周杰伦的show"+age);
  12. return "zhou";
  13. }
  14. /*此方法不能被代理(不能增强功能)
  15. public void one(){
  16. System.out.println("one..........");
  17. }*/
  18. }

ProxyFactory.java代理实例生成工厂

  1. public class ProxyFactory {
  2. Service target;
  3. public ProxyFactory(Service target){
  4. this.target=target;
  5. }
  6. //返回动态代理对象
  7. public Object getAgent(){
  8. return Proxy.newProxyInstance(
  9. //ClassLoader loader, 类加载器,完成目标对象的加载
  10. target.getClass().getClassLoader(),
  11. //Class<?>[] interfaces,目标对象实现的所有接口
  12. target.getClass().getInterfaces(),
  13. //InvocationHandler h); 实现代理功能的接口,我们传入的是匿名内部实现
  14. new InvocationHandler() {
  15. @Override
  16. public Object invoke(
  17. //创建代理对象
  18. Object proxy,
  19. //method就是目标方法sing() show()
  20. Method method,
  21. //目标方法的参数
  22. Object[] args) throws Throwable {
  23. //代理功能
  24. System.out.println("预定时间");
  25. //代理功能
  26. System.out.println("预定场地");
  27. //主业务功能实现
  28. // target.sing(); 写死了
  29. Object obj= method.invoke(target,args);
  30. //代理功能
  31. System.out.println("结算费用");
  32. return obj;//切记切记:这个是目标方法的返回值
  33. }
  34. }
  35. );
  36. }
  37. }

测试类

  1. public class MyTest {
  2. @Test
  3. public void testJdk() {
  4. ProxyFactory factory = new ProxyFactory(new SuperStarZhou());
  5. Service agent = (Service) factory.getAgent();
  6. agent.sing();
  7. agent.show(18);
  8. }
  9. }

CGLib动态代理(了解)

CGLib动态代理又称为子类.通过动态的在内存中构建子类对象,重写父类的方法进行代理功能的增强.
如果目标对象没有实现接口,则只能通过CGLib子类代理来进行功能增强.
子类代理是对象字节码框架ASM来实现的.
注意:
被代理的类不能为final, 否则报错.
目标对象的方法如果为final/static, 那么就不会被拦截,即不会执行目标对象额外的业务方法。

public Object getProxyInstance(){
//1.使用工具类
Enhancer en=new Enhancer();
//2.设置父类
en.setSuperclass(target.getClass());
//3.设置回调函数
en.setCallback(this);
//4.创建子类(代理)对象
return en.create(); ===>返回的是子类代理对象