在有的时候,我们在调用类的方法时,需要在类的方法前面和后面做一些事,比如说在每个方法前面打log,这时我们可以使用动态代理。动态代理分为JDK动态代理和CGLib动态代理。

 

1. JDK动态代理

被代理类实现的接口

package com.lk.proxy.service;

public interface PlanService {
    
    void addPlan(String plan);
    
    void deletePlan(int id);

}

被代理类

package com.lk.proxy.service.impl;

import com.lk.proxy.service.PlanService;

public class PlanServiceImpl implements PlanService {

    @Override
    public void addPlan(String plan) {
        System.out.println("execute add plan method, plan = " + plan);
    }

    @Override
    public void deletePlan(int id) {
        System.out.println("execute delete plan method");
    }

}

 

package com.lk.proxy.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class CustomProxyHandler implements InvocationHandler {
    private Object target;
    
    public CustomProxyHandler(Object target) {
        super();
        this.target = target;
    }

    public CustomProxyHandler() {
        super();
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("do some thing before invoke");
        Object result = method.invoke(target, args);
        System.out.println("do some thing after invoke");
        return result;
    }
    
    public void setTarget(Object target) {
        this.target = target;
    }

}

 

测试

package com.lk.proxy.test;

import java.lang.reflect.Proxy;

import com.lk.proxy.proxy.CustomProxyHandler;
import com.lk.proxy.service.PlanService;
import com.lk.proxy.service.impl.PlanServiceImpl;

public class TestProxy {
    public static void main(String[] args) {
        PlanService planServiceProxy = new PlanServiceImpl();
        CustomProxyHandler proxyHandler = new CustomProxyHandler(planServiceProxy);
        PlanService planService = (PlanService) Proxy.newProxyInstance(planServiceProxy.getClass().getClassLoader(), 
                planServiceProxy.getClass().getInterfaces(), proxyHandler);
        planService.addPlan("plan 1");
    }

}

 

2. CGLib动态代理

被代理类

package com.lk.proxydemo;

public class UserService {
    
    public void sayHello() {
        System.out.println("Say Hello");
    }

}

代理处理类

package com.lk.proxydemo;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor {
    private Enhancer enhancer = new Enhancer();
    
    public Object getProxy(Class<?> superClass) {
        //设置需要创建子类的类
        enhancer.setSuperclass(superClass);
        enhancer.setCallback(this);
        //通过字节码技术动态创建子类实例
        return enhancer.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args,
            MethodProxy proxy) throws Throwable {
        System.out.println("do some thing before " + method.getName());
        //通过代理类调用父类
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("do some thing after " + method.getName());
        return result;
    }

}

测试类

package com.lk.proxydemo;

public class ProxyTest {
    public static void main(String[] args) {
        CglibProxy proxy = new CglibProxy();
        UserService userService = (UserService) proxy.getProxy(UserService.class);
        userService.sayHello();
    }
}

 

3. 总结

  JDK动态代理中被代理类必须要实现相应接口,而CGLib不需要,CGLib是通过字节码技术为被代理类创建一个子类。

  CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时所花费的时间却比JDK多得多,所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,反之,使用JDK方式要更为合适一些。同时,由于CGLib由于是采用动态创建子类的方法,对于final方法,无法进行代理。

 

 

posted on 2013-12-11 19:53  寒岁青松  阅读(103)  评论(0)    收藏  举报