zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Windows server 2016 解决“无法完成域加入,原因是试图加入的域的SID与本计算机的SID相同。”
    Windows Server 2016 辅助域控制器搭建
    Windows Server 2016 主域控制器搭建
    Net Framework 4.7.2 覆盖 Net Framework 4.5 解决办法
    SQL SERVER 2012更改默认的端口号为1772
    Windows下彻底卸载删除SQL Serever2012
    在Windows Server2016中安装SQL Server2016
    SQL Server 创建索引
    C#控制台或应用程序中两个多个Main()方法的设置
    Icon cache rebuilding with Delphi(Delphi 清除Windows 图标缓存源代码)
  • 原文地址:https://www.cnblogs.com/hoje/p/8060080.html
Copyright © 2011-2022 走看看