静态代理
类似于装饰着模式,抽离到一定高度的时候,两者其实是一样的。
缺点:从代码就可以看出来,我们对两种方法所做的包装是一样的,但是同样的代码却写了两遍,如果再有相同的包装出现,那么又要进行同样逻辑的重写。
因为有相同包装出现,就要重写一次,闲的一点也不动态,所以就叫做静态代理。
public class StaticProxy {
static interface Subject{
void sayHi();
void sayHello();
}
static class SubjectImpl implements Subject {
@Override
public void sayHi() {
System.out.println("say hi");
}
@Override
public void sayHello() {
System.out.println("say hello");
}
}
public static class SubjectProxy implements Subject {
private Subject target;
public SubjectProxy(Subject target) {
this.target = target;
}
@Override
public void sayHi() {
System.out.println("first");
target.sayHi();
}
@Override
public void sayHello() {
System.out.println("first");
target.sayHello();
}
}
public static void main(String[] args) {
Subject subject = new SubjectImpl();
Subject subjectProxy = new SubjectProxy(subject);
subjectProxy.sayHello();
subjectProxy.sayHi();
}
}
JDK动态代理
总的来说,就是继承InvocationHandler,并且重写里面的invoke方法,invoke()通过反射去调用目标方法,Proxy动态的创建一个可代理的实例。
缺点:只提供接口的代理,不提供类的代理。(这里是通过被代理的接口动态的生成class类文件。如果看源码的话可以看到这个文件已经继承了Proxy类,而java是单继承的,因此不能再提供类的代理)
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DynamicProxy {
static interface Subject {
void sayHi();
void sayHello();
}
static class SubjectImpl implements Subject{
@Override
public void sayHi() {
System.out.println("say hi");
}
@Override
public void sayHello() {
System.out.println("say hello");
}
}
static class SubjectProxy implements InvocationHandler {
private Subject target;
public SubjectProxy(Subject target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("first:");
Object invoke = method.invoke(target, args);
if (method.getName().equals("sayHello")){
System.out.println("second");
}
return invoke;
}
}
//如果只想代理其中一个方法 也可以把想要代理的方法放到getInterFaces中
public static void main(String[] args) {
Subject subject = new SubjectImpl();
Class<?>[] interfaces = subject.getClass().getInterfaces();
//绑定需要关联到哪个接口的关系
Subject subjectProxy = (Subject) Proxy.newProxyInstance(subject.getClass().getClassLoader(), interfaces, new SubjectProxy(subject));
subjectProxy.sayHello();
subjectProxy.sayHi();
}
}
CGLib动态代理
通过调用enhancer的create()去创建代理对象。是针对目标对象生成一个子类,通过继承的方式来实现代理的,所以如果是final修饰的方法是没有办法做处理的。
package proxy;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class CGDynamicProxy {
static interface Subject {
void sayHi();
void sayHello();
}
static class SubjectImpl implements Subject{
@Override
public void sayHi() {
System.out.println("say hi");
}
@Override
public void sayHello() {
System.out.println("say hello");
}
}
static class SubjectProxy implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("first:");
Object obj = methodProxy.invokeSuper(o, objects);
System.out.println("second:");
return obj;
}
}
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
// 设置enhancer对象的父类
enhancer.setSuperclass(SubjectImpl.class);
// 设置enhancer的回调对象
enhancer.setCallback(new SubjectProxy());
// 创建代理对象
SubjectImpl proxy= (SubjectImpl)enhancer.create();
// 通过代理对象调用目标方法
proxy.sayHello();
}
}