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