老僧长谈设计模式-7-代理模式2

本文介绍了静态代理和两种动态代理(JDK动态代理与Cglib)的概念及实现方式,通过具体示例展示了如何利用代理模式进行面向切面编程(AOP),实现业务逻辑与辅助操作的解耦。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说明;

对前一篇 老僧长谈设计模式-7-代理模式 的补充

1.静态代理模式


讲一个说话和唱歌的故事,

你有一个接口ITalk,接口中有一个方法talk(),然后你还有一个Real Request类实现了ITalk接口。

但是光是说话满足不了全部人的要求,有的人还喜欢唱歌。

怎么办?难道在接口中再增加sing()方法吗?不可能的,那样的话所有该接口的实现类都不得不实现该方法啦。

此时一个聪明的办法是写一个代理类TalkProxy,其中不光有talk(),而且还有sing();

Proxy类

/**
 * 代理主题角色:内部包含对真实主题的引用,并且提供和真实主题角色相同的接口。
 * 
 * @author yanbin
 * 
 */
public class TalkProxy implements ITalk {

    private ITalk talker;

    public TalkProxy(ITalk talker) {
        // super();
        this.talker = talker;
    }

    public void talk(String msg) {
        talker.talk(msg);
    }
    
    /**
     * good,重载方法巧妙调用sing()
     * @param msg
     * @param singname
     */
    public void talk(String msg, String singname) {
        talker.talk(msg);
        sing(singname);
    }

    private void sing(String singname) {
        System.out.println("唱歌:" + singname);
    }

}


从这段代码可以看出来,代理模式其实就是AOP的雏形。 上端代码中talk(String msg, String singname)是一个切面。在代理类中的sing(singname)方法是个后置处理方法。

这样就实现了,其他的辅助方法和业务方法的解耦。业务不需要专门去调用,而是走到talk方法,顺理成章的调用sing方法

测试类

/**
 * 代理测试类,使用代理
 *
 * @author yanbin
 * 
 */
public class ProxyPattern {

    public static void main(String[] args) {
        // 不需要执行额外方法的。
        ITalk people = new PeopleTalk("AOP", "18");
        people.talk("No ProXY Test");
        System.out.println("-----------------------------");

        // 需要执行额外方法的(切面)
        ITalk talker = new new TalkProxy(people);
        talker.talk("ProXY Test", "千里之外");
    }

}



2.动态代理模式InvocationHandler

jdk1.5中提供,利用反射。实现java.lang.reflect.InvocationHandler接口

①必须要有一个业务接口

/**
 * @author         
 * @version        V1.0  
 * @Date           
 * @Email
 * @Description:   抽象主题角色 Subject
 */

public interface ITalk {
	public void talk(String msg);
}


②接口实现类

/**
 * @author         
 * @version        V1.0  
 * @Date            
 * @Email
 * @Description:   Real Request
 */

public class PeopleTalk implements ITalk {
	private String username;
	private String age;
	
	public PeopleTalk() {
		this("James", "30");
	}
	
	public PeopleTalk(String username, String age) {
		this.username = username;
		this.age = age;
	}
	

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getAge() {
		return age;
	}

	public void setAge(String age) {
		this.age = age;
	}


	@Override
	public void talk(String msg) {
		// TODO Auto-generated method stub
		System.out.println(msg + "!你好,我是" + this.getUsername() + ",年龄" + this.getAge());

	}

}


③动态代理类

/**
 * @author         
 * @version        V1.0  
 * @Date           
 * @Email
 * @Description:   动态代理 
 */

public class DynamicProxy implements InvocationHandler {
	/*需要代理的目标类*/
	private Object target;
	
	/**
	 * 绑定委托对象并返回一个代理类
	 * @param target
	 * @return
	 */
	public Object bind(Object target) {
		// TODO Auto-generated method stub
		this.target = target;
		/**
		 * 返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序
		 * @param loader - 定义代理类的类加载器
		 * @param interfaces - 代理类要实现的接口列表
		 * @param h - 指派方法调用的调用处理程序 InvocationHandler类invoke()方法
		 */
		return Proxy.newProxyInstance(target.getClass().getClassLoader(), 
				target.getClass().getInterfaces(), this);

	}

	/**
	 * @param Object proxy 被代理的对象
	 * @param Method method 要调用的方法
	 * @param Object[] args 方法调用时需要的参数 
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		// TODO Auto-generated method stub
		Object result = null;
		//切面之前执行
		System.out.println("切面之前执行.");
		//执行业务
		result = method.invoke(target, args);
		//切面之后执行
		System.out.println("切面之后执行.");
		return result;
	}

}

④测试类

/**
 * @author         
 * @version        V1.0  
 * @Date            
 * @Email
 * @Description:   代理测试类
 */

public class ProxyTest {
	public static void main(String[] args) {
		ITalk talk = (ITalk) new DynamicProxy().bind(new PeopleTalk());
		talk.talk("业务说明");
	}

}


3.动态代理Cglib

CGLIB是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强。采用的是继承的方式。

使用范围:对于不适用接口的业务类,无法使用JDK动态代理
原理:CGlib采用非常底层的字节码技术,可以为一个类创建子类,解决无接口类的代理类问题。

①业务类,不实现任何的接口

/** 
 * 该业务类没有实现任何接口 
 * @author dell 
 * 
 */  
public class Cat {  
  
    public void run(){  
        System.out.println("猫可以跑步。。。捉老鼠");  
    }  
}  

②动态代理类

import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Method;  
import java.lang.reflect.Proxy;  
  
import net.sf.cglib.proxy.Enhancer;  
import net.sf.cglib.proxy.MethodInterceptor;  
import net.sf.cglib.proxy.MethodProxy;  
  
import org.junit.Test;  
  
public class ProxyTest {  
      
    @Test  
    public void demo2(){  
        // cglib 动态代理  在目标业务类没有实现接口的情况下  
          
        // 1、创建真实业务对象的引用  
        Cat cat = new Cat();  
        // 2、创建真实业务类的子类  
        Enhancer enhancer = new Enhancer();  
        enhancer.setSuperclass(cat.getClass());  
          
        // 3、设置回调函数  
        enhancer.setCallback(new MethodInterceptor() {  
              
            @Override  
            public Object intercept(Object proxy, Method method, Object[] args,  
                    MethodProxy methodProxy) throws Throwable {  
                if(method.getName().equals("run")){  
                    System.out.println("cat的run方法被拦截了。。。。");  
                    Object invoke = method.invoke(proxy, args);  
                    System.out.println("真实方法拦截之后。。。。");  
                    return invoke;  
                }  
                  
                // 不拦截  
                return method.invoke(proxy, args);  
            }  
        });  
        Cat proxy = (Cat) enhancer.create();  
          
        proxy.run();  
    }  
} 


----------------------------------------------------------------------------

来源参考

http://blog.youkuaiyun.com/mrzhoug/article/details/51336833
设计模式(1)--理解AOP(代理模式)
http://blog.youkuaiyun.com/judyfun/article/details/45974223
Spring AOP的代理模式详解

内容概要:本文详细介绍了扫描单分子定位显微镜(scanSMLM)技术及其在三维超分辨体积成像中的应用。scanSMLM通过电调透镜(ETL)实现快速轴向扫描,结合4f检测系统将不同焦平面的荧光信号聚焦到固定成像面,从而实现快速、大视场的三维超分辨成像。文章不仅涵盖了系统硬件的设计与实现,还提供了详细的软件代码实现,包括ETL控制、3D样本模拟、体积扫描、单分子定位、3D重建和分子聚类分析等功能。此外,文章还比较了循环扫描与常规扫描模式,展示了前者在光漂白效应上的优势,并通过荧光珠校准、肌动蛋白丝、线粒体网络和流感A病毒血凝素(HA)蛋白聚类的三维成像实验,验证了系统的性能和应用潜力。最后,文章深入探讨了HA蛋白聚类与病毒感染的关系,模拟了24小时内HA聚类的动态变化,提供了从分子到细胞尺度的多尺度分析能力。 适合人群:具备生物学、物理学或工程学背景,对超分辨显微成像技术感兴趣的科研人员,尤其是从事细胞生物学、病毒学或光学成像研究的科学家和技术人员。 使用场景及目标:①理解和掌握scanSMLM技术的工作原理及其在三维超分辨成像中的应用;②学习如何通过Python代码实现完整的scanSMLM系统,包括硬件控制、图像采集、3D重建和数据分析;③应用于单分子水平研究细胞内结构和动态过程,如病毒入侵机制、蛋白质聚类等。 其他说明:本文提供的代码不仅实现了scanSMLM系统的完整工作流程,还涵盖了多种超分辨成像技术的模拟和比较,如STED、GSDIM等。此外,文章还强调了系统在硬件改动小、成像速度快等方面的优势,为研究人员提供了从理论到实践的全面指导。
内容概要:本文详细介绍了基于Seggiani提出的渣层计算模型,针对Prenflo气流床气化炉中炉渣的积累和流动进行了模拟。模型不仅集成了三维代码以提供气化炉内部的温度和浓度分布,还探讨了操作条件变化对炉渣行为的影响。文章通过Python代码实现了模型的核心功能,包括炉渣粘度模型、流动速率计算、厚度更新、与三维模型的集成以及可视化展示。此外,还扩展了模型以考虑炉渣组成对特性的影响,并引入了Bingham流体模型,更精确地描述了含未溶解颗粒的熔渣流动。最后,通过实例展示了氧气-蒸汽流量增加2%时的动态响应,分析了温度、流动特性和渣层分布的变化。 适合人群:从事煤气化技术研究的专业人士、化工过程模拟工程师、以及对工业气化炉操作优化感兴趣的科研人员。 使用场景及目标:①评估不同操作条件下气化炉内炉渣的行为变化;②预测并优化气化炉的操作参数(如温度、氧煤比等),以防止炉渣堵塞;③为工业气化炉的设计和操作提供理论支持和技术指导。 其他说明:该模型的实现基于理论公式和经验数据,为确保模型准确性,实际应用中需要根据具体气化炉的数据进行参数校准。模型还考虑了多个物理场的耦合,包括质量、动量和能量守恒方程,能够模拟不同操作条件下的渣层演变。此外,提供了稳态求解器和动态模拟工具,可用于扰动测试和工业应用案例分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值