静态代理
public class Demo {
public static void main(String[] args) {
ProxyPerson proxyPerson = new ProxyPerson();
proxyPerson.work();
System.out.println(proxyPerson.say());
}
}
interface Person{
void work();
String say();
}
class Personimpl implements Person{
@Override
public void work() {
System.out.println("普通人");
}
@Override
public String say() {
return "hello";
}
}
class ProxyPerson implements Person{
private Personimpl person = new Personimpl();
@Override
public void work() {
System.out.println("检查一下我是谁!");
System.out.print("我不是");
person.work();
System.out.println("我是程序员!");
}
@Override
public String say() {
System.out.println("检查一下我是谁!");
return person.say()+" beauty";
}
}
特点:代理类和被代理的类应该拥有的相同方法列表,所以应该是一个接口的共同接口。结构简单易懂,但是对于被代理的类如果方法特别多的话就会可能有太多地方代码重复。
动态代理
import java.lang.reflect.Proxy;
public class Demo {
public static void main(String[] args) {
Personimpl personimpl = new Personimpl();
Person person = (Person) Proxy.newProxyInstance(personimpl.getClass().getClassLoader(), personimpl.getClass().getInterfaces(),
(proxy,method,argss)->{
Object returnObject;
System.out.println("检查一下我是谁!");
if(method.getName().equals("work")) {
System.out.print("我不是");
returnObject = method.invoke(personimpl, argss);
System.out.println("我是程序员!");
}else {
returnObject = method.invoke(personimpl, argss);
returnObject +=" beauty";
}
return returnObject;
});
person.work();
System.out.println(person.say());
}
}
interface Person{
void work();
String say();
}
class Personimpl implements Person{
@Override
public void work() {
System.out.println("普通人");
}
@Override
public String say() {
return "hello";
}
}
特点:利用java自带的反射包中Proxy类的newProxyInstance方法创建一个实现了被代理类所有接口的对象,看情况拿其中某一个接口取出(向上造型)。这个方法有三个参数,第一个是被代理类的加载器,第二个就是被代理类的所有接口(接口数组类型,利用反射获取),第三个是InvocationHandler,用于操作代理类具体的功能,InvocationHandler是一个函数式接口,他的方法invoke(Object proxy, Method method, Object[] args),第一参数是代理者(基本不会用),第二个参数是方法,第三个参数是方法的参数们。
和静态相比不用每个方法都去写一遍,所有方法都会走这个,包括Object自带的方法。最大的缺点是必须想要增强的方法必须在某个接口中,并且被代理类必须实现这个接口。如果实在没有接口,可以导入第三方框架cglib,他是基于继承实现动态代理,不是一定需要接口。