您的位置:首页 > 编程语言 > Java开发

java中代理-静态代理

2019-02-20 11:34 98 查看

明明可以直接调通的对象方法为什么还要使用代理?随着学习的不断深入和工作经验的积累,慢慢的体会并理解了java代理机制。 
在业务中,我们用action调用service的方法实现业务即可。
由于之前在service中实现的业务可能不能够满足当先客户的要求,需要我们重新修改service中的方法,但是service的方法不只在我们这个模块使用,在其他模块也在调用,其他模块调用的时候,现有的service方法已经能够满足业务需求,所以我们不能只为了我们的业务而修改service,导致其他模块授影响。
那怎么办呢?
可以通过动态代理的方式,扩展我们的service中的方法实现,使得在原有的方法中增加更多的业务,而不是实际修改service中的方法,这种实现技术就叫做代理。
代理:在不修改原业务的基础上,基于原业务方法,进行重新的扩展,实现新的业务

举一个现实生活中的例子:歌星或者明星都有一个自己的经纪人,这个经纪人就是他们的代理人,当我们需要找明星表演时,不能直接找到该明星,只能是找明星的代理人。比如刘德华在现实生活中非常有名,会唱歌,会跳舞,会拍戏,刘德华在没有出名之前,我们可以直接找他唱歌,跳舞,拍戏,刘德华出名之后,他干的第一件事就是找一个经纪人,这个经纪人就是刘德华的代理人(代理),当我们需要找刘德华表演时,不能直接找到刘德华了(刘德华说,你找我代理人商谈具体事宜吧!),只能是找刘德华的代理人,因此刘德华这个代理人存在的价值就是拦截我们对刘德华的直接访问!
  
这个现实中的例子和我们在开发中是一样的,我们在开发中之所以要产生一个对象的代理对象,主要用于拦截对真实业务对象的访问。那么代理对象应该具有什么方法呢?代理对象应该具有和目标对象相同的方法

所以在这里明确代理对象的两个概念:
    
1、代理对象存在的价值主要用于拦截对真实业务对象的访问。
   
2、代理对象应该具有和目标对象(真实业务对象)相同的方法。刘德华(真实业务对象)会唱歌,会跳舞,会拍戏,我们现在不能直接找他唱歌,跳舞,拍戏了,只能找他的代理人(代理对象)唱歌,跳舞,拍戏,一个人要想成为刘德华的代理人,那么他必须具有和刘德华一样的行为(会唱歌,会跳舞,会拍戏),刘德华有什么方法,他(代理人)就要有什么方法,我们找刘德华的代理人唱歌,跳舞,拍戏,但是代理人不是真的懂得唱歌,跳舞,拍戏的,真正懂得唱歌,跳舞,拍戏的是刘德华,在现实中的例子就是我们要找刘德华唱歌,跳舞,拍戏,那么只能先找他的经纪人,交钱给他的经纪人,然后经纪人再让刘德华去唱歌,跳舞,拍戏。

(1)什么是代理?
大道理上讲代理是一种软件设计模式,目的地希望能做到代码重用。具体上讲,代理这种设计模式是通过不直接访问被代理对象的方式,而访问被代理对象的方法。
这个就好比 商户---->明星经纪人(代理)---->明星这种模式。我们可以不通过直接与明星对话的情况下,而通过明星经纪人(代理)与其产生间接对话。

(2)什么情况下使用代理?
(1)设计模式中有一个设计原则是开闭原则,是说对修改关闭对扩展开放,我们在工作中有时会接手很多前人的代码,里面代码逻辑让人摸不着头脑(),这时就很难去下手修改代码,那么这时我们就可以通过代理对类进行增强。
(2)我们在使用RPC框架的时候,框架本身并不能提前知道各个业务方要调用哪些接口的哪些方法 。那么这个时候,就可用通过动态代理的方式来建立一个中间人给客户端使用,也方便框架进行搭建逻辑,某种程度上也是客户端代码和框架松耦合的一种表现。
(3)Spring的AOP机制就是采用动态代理的机制来实现切面编程。

(3)静态代理和动态代理
我们根据加载被代理类的时机不同,将代理分为静态代理和动态代理。
如果我们在代码编译时就确定了被代理的类是哪一个,那么就可以直接使用静态代理;
如果不能确定,那么可以使用类的动态加载机制,在代码运行期间加载被代理的类这就是动态代理,比如RPC框架和Spring AOP机制。

(4)静态代理
我们先创建一个接口,遗憾的是java api代理机制求被代理类必须要实现某个接口,
对于静态代理方式代理类也要实现和被代理类相同的接口;
对于动态代理代理类则不需要显示的实现被代理类所实现的接口。
首先定义 接口 Person
/**

  • 顶层接口
  • @author wang

*/
public interface Person {
public void sayHello(String content, int age);
public void sayGoodBye(boolean seeAgin, double time);
}

其次定义接口的实现类。 类中实现的方法是初次的过去的业务逻辑
/**

  • 需要被代理的类 实现了一个接口Person
  • @author wang

*/
public class Student implements Person{

@Override
public void sayHello(String content, int age) {
// TODO Auto-generated method stub
System.out.println("student say hello" + content + " "+ age);
}

@Override
public void sayGoodBye(boolean seeAgin, double time) {
// TODO Auto-generated method stub
System.out.println("student sayGoodBye " + time + " "+ seeAgin);
}

}
静态代理类登场
/**

  • 静态代理,这个代理类也必须要实现和被代理类相同的Person接口
  • @author yujie.wang

*/
public class ProxyTest implements Person{

private Person o; /**这是用来处理被代理的Student 这个类 的,定义目的就是为了操作Student的原有逻辑方法*/

public ProxyTest(Person o){
this.o = o;
}

public static void main(String[] args) {
// TODO Auto-generated method stub
//s为被代理的对象,某些情况下 我们不希望修改已有的代码,我们采用代理来间接访问
Student s = new Student();
//创建代理类对象
ProxyTest proxy = new ProxyTest(s);
//调用代理类对象的方法
proxy.sayHello("welcome to java", 20);
System.out.println("******");
//调用代理类对象的方法
proxy.sayGoodBye(true, 100);

}

因为实现了Person接口,所以,必须实现接口内方法
@Override
public void sayHello(String content, int age) {
// TODO Auto-generated method stub
System.out.println(“ProxyTest sayHello begin”);
//在代理类的方法中 间接访问被代理对象的方法
o.sayHello(content, age); 此处访问原Student 类的相应方法
System.out.println(“ProxyTest sayHello end”);
}

@Override
public void sayGoodBye(boolean seeAgin, double time) {
// TODO Auto-generated method stub
System.out.println("ProxyTest sayHello begin");
//在代理类的方法中 间接访问被代理对象的方法
o.sayGoodBye(seeAgin, time);
System.out.println("ProxyTest sayHello end");
}

}

测试代码输出:

ProxyTest sayHello begin
student say hellowelcome to java 20
ProxyTest sayHello end

ProxyTest sayHello begin
student sayGoodBye 100.0 true
ProxyTest sayHello end

静态代理看起来是比较简单的,没有什么问题只不过是在代理类中引入了被代理类的对象而已。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: