代理模式
应用场景:不该变源代码,给源代码增加功能。
在Java中,常用的代理有JDK动态代理和cglib动态代理。JDK动态代理由java.lang.reflect包下的Proxy提供的,基于接口生成的代理类,实现对目标类的代理;cglib是由Oracle提供的Java开发工具包,采用字节码技术,直接修改字节码并生成代理子类。
注意:JDK动态代理中,调用方法时其代理类并不知道目标类的具体方法,因此需要通过反射来进行调用,效率很低。
JDK实现动态代理
java
public class Person implements IPerson {
@Override
public void eat(){
System.out.println("开始吃饭");
}
}
1.定义接口,定义需要代理的方法
java
public interface IPerson {
public void eat();
}
2.定义类并创建代理对象
java
public static IPerson createPersonProxy(Person person){
IPerson iPersonProxy = (IPerson) Proxy.newProxyInstance(PersonProxy.class.getClassLoader()
, new Class[]{IPerson.class}
, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName() == "eat"){
System.out.println("拿筷子");
System.out.println("拿碗");
}
return method.invoke(person ,args);
}
});
return iPersonProxy;
}
}
3.调用代理对象的方法
java
public class Demo {
public static void main(String[] args) {
Person person = new Person();
IPerson personProxy = PersonProxy.createPersonProxy(person);
personProxy.eat();
}
}
CGLIB实现动态代理
java
public class Person{
public void eat(){
System.out.println("开始吃饭");
}
}
java
public class PersonProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz){
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
//通过字节码技术动态创建子类实例
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
if(method.getName().equals("eat")){
System.out.println("拿筷子");
System.out.println("拿碗");
}
//通过代理类调用父类中的方法
Object result = methodProxy.invokeSuper(o, objects);
return result;
}
}