Java代理模式

 一、代理模式的介绍

       代理模式,是指对一个对象提供一种代理以控制对这个对象的访问。使用代理对象,是为了在不修改目标对象的基础上,增强主业务逻辑。

       客户类真正想访问的是目标对象,但客户类可以访问的对象是代理对象。可以以“代理律师”来理解“代理模式”。

二、包的命名

      JAVA中包的命名一般分为4-5层:

     1、甲方公司域名的倒叙           com.jmu

     2、项目名称                            oa

     3、模块信息                            xxx

     4、功能顶层包                       service、dao、beans、vo 

     5、实现类  (有些功能包没有实现类)                             impl

     例: com.jmu.oa.xxx.dao.impl

   之所以要这样命名项目中的包,是为了保证项目中所用到的类具有全球唯一性。

    实体

    beans、entity、持久化对象po(Persistance Object)

   以上包中所存放的类,数据库中有其对应的表,一般有id 属性。

    vo:Value Object,值对象。一般用于类和页面之间传值

   dto:Data  Transter Object, 数据传输对象,一般用于类间传值。

 以上包中所存放的类,数据库中没有其对应的表,用于类和类之间、类和对象之间传值,一般没有id属性。因为它们不需要持久化。仅仅是用于在代码中进行数据传递。

dao: Data Access Object 数据访问对象,增删改查

三、代理环境的搭建

public interface ISomeService {
 String doFirst();
 void doSecond();
}

  

public class SomeServiceImpl implements ISomeService{

    @Override
    public String doFirst() {
        // TODO Auto-generated method stub
        System.out.println("执行doFirst()方法");
        return "abcde";
    }

    @Override
    public void doSecond() {
        // TODO Auto-generated method stub
        System.out.println("执行doSecond()方法");
        
    }

}
 1 public class MyTest {
 2 
 3     public static void main(String[] args) {
 4         // TODO Auto-generated method stub
 5         ISomeService service=new SomeServiceImpl();
 6         String result =service.doFirst();
 7         System.out.println("result="+result);
 8         service.doSecond();
 9     }
10 
11 }

输出:

执行doFirst()方法
result=abcde
执行doSecond()方法

四、静态代理的实现

静态代理:代理类在程序运行前已经定义好,其与目标类的关系在程序运行前已经确立。

案例要求:

要求输出大写的ABCD

 1 import com.jmu.service.ISomeService;
 2 import com.jmu.serviceImpl.SomeServiceImpl;
 3 //代理类
 4 public class SomeServiceProxy implements ISomeService{
 5 
 6     private ISomeService target;
 7 
 8     public SomeServiceProxy() {
 9         target = new SomeServiceImpl();
10     }
11 
12     @Override
13     public String doFirst() {
14         //代理类调用目标方法
15         String result=target.doFirst();
16         //增强        
17         return result.toUpperCase();
18     }
19 
20     @Override
21     public void doSecond() {
22         // TODO Auto-generated method stub
23         target.doSecond();
24     }
25 
26 }

输出:

执行doFirst()方法
result=ABCDE
执行doSecond()方法

  

(视频中的理解图)

五、动态代理

1、JDK动态代理

使用JDK的Proxy动态代理,要求目标类必须实现接口,因为其底层的实现原理和静态代理一样。

在之前基础上删除 SomeServiceProxy类,然后

 1 import java.lang.reflect.InvocationHandler;
 2 import java.lang.reflect.Method;
 3 import java.lang.reflect.Proxy;
 4 
 5 import com.jmu.service.ISomeService;
 6 import com.jmu.serviceImpl.SomeServiceImpl;
 7 
 8 public class MyTest {
 9 
10     public static void main(String[] args) {
11         // TODO Auto-generated method stub
12         ISomeService target=new SomeServiceImpl();
13         ISomeService service=(ISomeService) Proxy.newProxyInstance(
14                 target.getClass().getClassLoader(),//目标类的类加载器
15                 target.getClass().getInterfaces(), //目标类所实现的所有接口
16                 new  InvocationHandler() {          //匿名内部类
17                     //proxy:代理对象
18                     //method:目标对象
19                     //args:目标对象的参数列表
20                     @Override
21                     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
22                         // TODO Auto-generated method stub
23                         //调用目标方法
24                         Object result = method.invoke(target, args);
25                     
26                         if (result!=null) {
27                             result = ((String) result).toUpperCase();
28                         }
29                         return result;
30                     }
31                 });
32         String result =service.doFirst();
33         System.out.println("result="+result);
34         service.doSecond();
35     }
36 
37 }

2、CGLIB动态代理

对于无接口的类,要为其创建动态代理,就要用CGLIB来实现。CGLIB代理的生成原理是生成目标类的子类,而子类是增强过的,这个子类对象就是代理对象。所以,使用CGLIB生成动态代理,要求目标类能被继承,不能是final的类。

对于有接口的类,以为其有子类,所以也会有CGLIB动态代理。

首先,添加cglib包

还涉及方法回调设计模式

(1)无接口

public class SomeService {


    public String doFirst() {
        // TODO Auto-generated method stub
        System.out.println("执行doFirst()方法");
        return "abcde";
    }

    
    public void doSecond() {
        // TODO Auto-generated method stub
        System.out.println("执行doSecond()方法");
        
    }

}
 1 package com.jmu.factory;
 2 
 3 import java.lang.reflect.Method;
 4 
 5 import com.jmu.service.SomeService;
 6 
 7 import net.sf.cglib.proxy.Enhancer;
 8 import net.sf.cglib.proxy.MethodInterceptor;
 9 import net.sf.cglib.proxy.MethodProxy;
10 
11 public class MyCglibFactory implements MethodInterceptor {
12     private SomeService target;
13 
14     public MyCglibFactory() {
15         target = new SomeService();
16     }
17 
18     public SomeService myCglibCreator() {
19         // 创建增强器对象
20         Enhancer enhancer = new Enhancer();
21         // 指定目标类,即父类
22         enhancer.setSuperclass(SomeService.class);
23         // 设置回调接口对象
24         enhancer.setCallback(this);
25         return (SomeService) enhancer.create();
26     }
27 
28     // 回调方法
29     @Override
30     public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
31         Object result = method.invoke(target, args);
32         
33         if (result!=null) {
34             result = ((String) result).toUpperCase();
35         }
36         return result;
37     }
38 }
 1 package com.jmu.test;
 2 
 3 import com.jmu.factory.MyCglibFactory;
 4 import com.jmu.service.SomeService;
 5 
 6 public class MyTest {
 7 
 8     public static void main(String[] args) {
 9         // TODO Auto-generated method stub
10         SomeService service=new MyCglibFactory().myCglibCreator();
11         String result =service.doFirst();
12         System.out.println("result="+result);
13         service.doSecond();
14     }
15 
16 }

(2)有接口

1 package com.jmu.service;
2 //业务接口
3 public interface ISomeService {
4 //目标方法
5  String doFirst();
6  void doSecond();
7 }
 1 package com.jmu.service;
 2 
 3 import com.jmu.service.ISomeService;
 4 //目标类
 5 public class SomeServiceImpl implements ISomeService{
 6 
 7     @Override
 8     public String doFirst() {
 9         // TODO Auto-generated method stub
10         System.out.println("执行doFirst()方法");
11         return "abcde";
12     }
13 
14     @Override
15     public void doSecond() {
16         // TODO Auto-generated method stub
17         System.out.println("执行doSecond()方法");
18         
19     }
20 
21 }
 1 package com.jmu.factory;
 2 
 3 import java.lang.reflect.Method;
 4 
 5 import com.jmu.service.ISomeService;
 6 import com.jmu.service.SomeServiceImpl;
 7 
 8 import net.sf.cglib.proxy.Enhancer;
 9 import net.sf.cglib.proxy.MethodInterceptor;
10 import net.sf.cglib.proxy.MethodProxy;
11 
12 public class MyCglibFactory implements MethodInterceptor {
13     private ISomeService target;
14 
15     public MyCglibFactory() {
16         target = new SomeServiceImpl();
17     }
18 
19     public ISomeService myCglibCreator() {
20         // 创建增强器对象
21         Enhancer enhancer = new Enhancer();
22         // 指定目标类,即父类
23         enhancer.setSuperclass(ISomeService.class);
24         // 设置回调接口对象
25         enhancer.setCallback(this);
26         return (ISomeService) enhancer.create();
27     }
28 
29     // 回调方法
30     @Override
31     public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
32         Object result = method.invoke(target, args);
33         
34         if (result!=null) {
35             result = ((String) result).toUpperCase();
36         }
37         return result;
38     }
39 }
 1 package com.jmu.test;
 2 
 3 import com.jmu.factory.MyCglibFactory;
 4 import com.jmu.service.ISomeService;
 5 
 6 public class MyTest {
 7 
 8     public static void main(String[] args) {
 9         // TODO Auto-generated method stub
10         ISomeService service=new MyCglibFactory().myCglibCreator();
11         String result =service.doFirst();
12         System.out.println("result="+result);
13         service.doSecond();
14     }
15 
16 }
原文地址:https://www.cnblogs.com/hoje/p/8060080.html