代理分为两种:静态代理、动态代理
静态代理:代理类是程序员创建或特定工具自动生成源代码再对其编译。在程序运行前代理类的.class文件就已经存在。设计模式中的代理模式使用的就是静态代理。
动态代理:有2种实现方式,一种是使用JDK的反射机制生成代理;另一种是cglib来生成代理。动态代理可以在程序运行期间根据需要动态的创建代理类及其实例,来完成具体的功能。
首先,介绍一下设计模式中的代理模式。
代理模式就是存在一个代理类,代理类和被代理类需要实现同一个接口,代理类调用被代理类对象中的相关方法,并且可以对产生的结果添加业务逻辑。使用代理可以在不改变目标对象方法的情况下对原方法的逻辑进行增强。
接口类
public interface IAnimal{
public void sound();
}
被代理类
public class Cat implements IAnimal{
@Override
public void sound() {
System.out.println("miao miao");
}
}
代理类
public class CatProxy implements IAnimal{
private IAnimal animal;
public CatProxy(IAnimal animal) {
this.animal=animal;
}
@Override
public void sound() {
System.out.println("CatProxy method sound begin");
animal.sound();
System.out.println("CatProxy method sound end");
}
}
测试类
public class Test {
public static void main(String[] args) {
IAnimal animal=new Cat();//接口的引用指向实现类的对象
CatProxy catProxy=new CatProxy(animal);
catProxy.sound();//通过代理类调用委托类的sound方法
}
}
输出:
静态代理有一个最大的缺陷:接口与代理类是1对1的,如果有多个接口需要代理,那就需要新建多个代理类。
只能对接口进行代理,不能对普通的类进行代理,使用Java原生的反射API
需要提供一个接口,通过创建代理类,实现调用方与具体实现的解耦。
实现InvocationHandler接口中代理类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class AnimalInvocationHandler implements InvocationHandler{
private Object object;
public AnimalInvocationHandler(Object object) {
this.object=object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("AnimalInvocationHandler invoke begin");
Object result=method.invoke(object, args);//调用object所指向的实现类实例对象的method方法,args为调用方法传递过来的实参
System.out.println("AnimalInvocationHandler invoke end");
return result;
}
}
测试类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) {
// IAnimal animal=new Cat();//接口的引用指向实现类的对象
// CatProxy catProxy=new CatProxy(animal);
// catProxy.sound();//通过代理类调用委托类的sound方法
IAnimal animal=new Cat();//接口的引用指向实现类的对象
InvocationHandler handler = new AnimalInvocationHandler(animal);
IAnimal proxy = (IAnimal) Proxy.newProxyInstance(IAnimal.class.getClassLoader(), new Class[]{IAnimal.class}, handler);
proxy.sound();
}
}
输出内容:
能够代理普通类,cglib使用asm框架直接对字节码进行操作。
引入cglib相关的jar包:cglib-2.2.jar
若是maven项目,可以添加如下dependency
cglib
cglib
2.2
被代理类,不再实现Animal接口
public class Cat{
public void sound() {
System.out.println("miao miao");
}
}
代理类
import java.lang.reflect.Method;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CgLibProxy implements MethodInterceptor{
@Override
public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("CgLibProxy method intercept begin");
Object intercept = methodProxy.invokeSuper(object, args);
System.out.println("CgLibProxy method intercept end");
return intercept;
}
}
测试类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import net.sf.cglib.proxy.Enhancer;
public class Test {
public static void main(String[] args) {
// IAnimal animal=new Cat();//接口的引用指向实现类的对象
// CatProxy catProxy=new CatProxy(animal);
// catProxy.sound();//通过代理类调用委托类的sound方法
// IAnimal animal=new Cat();//接口的引用指向实现类的对象
// InvocationHandler handler = new AnimalInvocationHandler(animal);
// IAnimal proxy = (IAnimal) Proxy.newProxyInstance(IAnimal.class.getClassLoader(), new Class[]{IAnimal.class}, handler);
// proxy.sound();
CgLibProxy cgLibProxy=new CgLibProxy();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Cat.class);
enhancer.setCallback(cgLibProxy);
Cat proxy = (Cat) enhancer.create();
proxy.sound();
}
}
右键run as--java application,控制台console中报如下错误:
添加jar包:asm-3.3.1.jar
执行成功,输出结果如下: