java 代理的三种实现方式

java

Java 代理模式有如下几种实现方式:

  1.静态代理。    

      2.JDK动态代理。

      3.CGLIB动态代理。

示例,有一个打招呼的接口。分别有两个实现,说hello,和握手。代码如下。

接口:

public interface Greeting {

public void doGreet();

}

实现类:

public class SayHello implements Greeting {

@Override

public void doGreet() {

System.out.println("Greeting by say 'hello' .");

}

}

public class ShakeHands implements Greeting {

@Override

public void doGreet() {

System.out.println("Greeting by shake others's hands .");

}

}

public class KissHello  {

public void doGreet() {

System.out.println("Greeting by kiss . ");

}

}

在不改变代码的情况下,想在执行目标方法 前后 做一些其他操作。则可以通过代理方式来实现。

1.静态代理。需要创建代理类。代理类实现了和目标类一样的接口,代理类接收目标类对象,并在实现方法中调用目标类的实现方法前后做手脚。如下:

public class GreetStaticProxy implements Greeting {

private Greeting hello;//被代理对象

public GreetStaticProxy(Greeting hello){

this.hello=hello;

}

@Override

public void doGreet() {

before();//执行其他操作

this.hello.doGreet();//调用目标方法

after();//执行其他操作

}

public void before(){

System.out.println("[StaticProxy] Come to someone.");

}

public void after(){

System.out.println("[StaticProxy] Back to his own corner");

}

}

测试调用:

public class Main {

public static void main(String[] args) {

Greeting hello=new SayHello();

Greeting shakeHands=new ShakeHands();

//静态代理

GreetStaticProxy staticHelloProxy=new GreetStaticProxy(hello);

staticHelloProxy.doGreet();

System.out.println();

GreetStaticProxy shakeHandsProxy=new GreetStaticProxy(shakeHands);

shakeHandsProxy.doGreet();

}

运行结果:
[StaticProxy] Come to someone.

Greeting by say 'hello' .

[StaticProxy] Back to his own corner

[StaticProxy] Come to someone.

Greeting by shake others's hands .

[StaticProxy] Back to his own corner

这个方式有弊端,如果有N个接口的实现类需要被代理,则需要创建N个代理类。

2.JDK动态代理

创建代理类,如下:

public class JdkProxy implements InvocationHandler {

private Object target;

public JdkProxy(Object obj){

this.target=obj;

}

@Override

public Object invoke(Object proxy, Method method, Object[] args)

throws Throwable {

Object result=null;

before();

result=method.invoke(target, args);

after();

return result;

}

public void before(){

System.out.println("[JdkProxy] Come to someone.");

}

public void after(){

System.out.println("[JdkProxy] Back to his own corner");

}

}

测试调用:

public class Main {

public static void main(String[] args) {

Greeting hello=new SayHello();

Greeting shakeHands=new ShakeHands();

//jdk动态代理

JdkProxy dynamicProxy=new JdkProxy(hello);

Greeting target=(Greeting) Proxy.newProxyInstance(hello.getClass().getClassLoader(),

hello.getClass().getInterfaces(), dynamicProxy);

target.doGreet();

System.out.println();

}

}

这种方式和第一种方式相比,虽然不需要创建很多代理类,

但是,他依赖与“被代理的对象需要实现接口” 即:在上面给出的代码示例中,动态代理可以代理SayHello和ShakeHands,却不能代理KissHello。因为KissHello没有实现接口。

3.CGLIB动态代理。

创建代理类:

public class CglibProxy implements MethodInterceptor {

public static CglibProxy proxy=new CglibProxy();

private CglibProxy(){}

public static CglibProxy getInstance(){

return proxy;

}

public <T> T getProxy(Class<T> cls){

return (T) Enhancer.create(cls, this);

}

@Override

public Object intercept(Object obj, Method method, Object[] arg,

MethodProxy proxy) throws Throwable {

Object result=null;

try {

before();

result= proxy.invokeSuper(obj, arg);

after();

} catch (Exception e) {

e.printStackTrace();

}

return result;

}

public void before(){

System.out.println("[cglib] Come to someone.");

}

public void after(){

System.out.println("[cglib] Back to his own corner.");

}

}

调用示例:

public class Main {

public static void main(String[] args) {

//cglib代理

Greeting targetProxy=CglibProxy.getInstance().getProxy(SayHello.class);

targetProxy.doGreet();

System.out.println();

CglibProxy.getInstance().getInstance().getProxy(KissHello.class).doGreet();

}

}

综上,CGLIB动态代理最好,spring框架也用到了CGLIB包。

以上是 java 代理的三种实现方式 的全部内容, 来源链接: utcz.com/z/392005.html

回到顶部