JAVA动态代理的简单使用
一、为啥不用静态代理?
1、静态代理需要实现生成class文件。
2、静态代理需要实现被代理者的所有方法。
例子:假设被代理类有n个方法需要代理类增强功能,即使增强的功能相同,代理类也需要实现这n个方法。
3、一个静态代理类只能代理一个接口。
例子:假设有n个被代理接口都需要增强相同的功能,那么需要n个静态代理。
//需要代理两个方法,代码重复
public class StaticAnimalProxy implements Animal{
private Animal animal;
@Override
public void say(){
System.out.println("before");
animal.say();
System.out.println("after");
}
@Override
public void eat() {
System.out.println("before");
animal.eat();
System.out.println("after");
}
public StaticAnimalProxy(Animal animal){
this.animal = animal;
}
}
二、JDK原生动态代理
- 通过InvocationHandler的invoke方法来回调被代理类的方法。根据给定的类加载器,接口名通过Proxy的newProxyInstance来生成代理实例。
- jdk动态代理是通过java反射动态生成代理类的,生成的代理类为Proxy的子类并实现了被代理类的接口。因为是组合关系所有可代理final方法。
对指定方法进行代理
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().equals("eat")){
method.invoke(obj,args);
return null;
}
System.out.println("before");
method.invoke(obj,args);
System.out.println("after");
return null;
}
生成代理对象。
public static Animal getAnProxy(Animal animal){
DynamicAnimalProxyHandler handler = new DynamicAnimalProxyHandler(animal);
Animal animalProxy = (Animal) Proxy.newProxyInstance(animal.getClass().getClassLoader(),animal.getClass().getInterfaces(),handler);
return animalProxy;
}
三、Cglib动态代理
1、通过使用ASM包,修改被代理类的字节码文件生成一个新的class文件来作为代理类。生成的代理类继承自父类而非接口,因此不能代理final方法。
2、通过MethodInteceptor的intecepter回调父类的方法并增强功能。
被代理类
public class Animal {
public final void say(){
System.out.println("happy");
}
public void run(){
System.out.println("run");
}
public void sing(){
System.out.println("sing");
}
}
MethodInterceptor
public class AnimalMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
if(method.getName().equals("sing")){
return methodProxy.invokeSuper(o,objects);
}
System.out.println("before");
Object answer = methodProxy.invokeSuper(o,objects);
System.out.println("after");
return answer;
}
}
测试
public class Test {
public static void main(String[] args){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Animal.class);
enhancer.setCallback(new AnimalMethodInterceptor());
Animal proxy = (Animal)enhancer.create();
proxy.run();
proxy.say();
proxy.sing();
}
}