第一章:什么是动态代理

       当想要给某个类的某个方法,添加一些额外的处理。可以创建一个代理类,在执行这个方法前后执行想要添加的逻辑。如果在程序运行前就定义好这个代理类,叫做静态代理;如果在程序运行时创建这个类,叫做动态代理。

第二章:使用JDK动态代理实现

       第一步:创建需要代理的接口

/**
 *
该类是被代理类的接口类,JDK的代理要求被代理类基于统一的接口
 
*/
public interface Service {
    //add 方法
   
void add();
    //update 方法
   
void update();
}

       第二步:创建目标类,实现这个接口

/**
 *
实现Service接口的A
 
*/
public class AServiceImp implements Service {
    public void add() {
        System.out.println("=======>>add from A");
    }
    public void update() {
        System.out.println("=======>>update from A");
    }
}

       第三步:实现InvocationHandler 接口,实现invoke方法,处理代理逻辑和执行目标方法

/**
 *
实现InvocationHandler 目标类方法的执行就是有method.invoke()完成的
 
* invoke方法中加入切面逻辑
 
*/
public class ServiceInvocationHandler implements InvocationHandler {
    private Object target;
    ServiceInvocationHandler() {
        super();
    }
    ServiceInvocationHandler(Object target) {
        super();
        this.target = target;
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //程序执行前逻辑
       
System.out.println("before------------");
        //程序执行
       
Object result = method.invoke(target, args);
        //程序执行后逻辑
       
System.out.println("after-------------");
        return result;
    }
}

       第四步:测试

/**
 *
测试类
 
*/
public class Test {
    public static void main(String[] args) {
        Service serviceA = new AServiceImp();
        ServiceInvocationHandler handeler = new ServiceInvocationHandler(serviceA);
        Service serviceProxy = (Service) Proxy.newProxyInstance(serviceA.getClass().getClassLoader(),
                serviceA.getClass().getInterfaces(), handeler);
        serviceProxy.add();
        serviceProxy.update();
    }
}

控制台输出:

before------------

=======>>add from A

after-------------

before------------

=======>>update from A

after-------------

第三章,使用cglib进行动态代理

       第一步:引入jar包,cglib主要使用ASM框架操作字节码

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.5</version>
</dependency>

       第二步:创建目标类,cglib不需要同一的接口

/**
 *
需要被代理的类,cglib不需要定义目标类的同一接口
 
*/
public class Service {
    //模拟的add方法
   
public void add() {
        System.out.println("add-------");
    }
}
        第三步:创建代理类,实现MethodInterceptor接口。
/**
 * Service
的代理类,实现MethodInterceptor接口
 
* intercept中加入切面逻辑
 
* 目标执行预计语句是
 
*/
public class ServiceProxy implements MethodInterceptor {
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        //执行前逻辑
       
System.out.println("before--------->");
        //程序执行
       
Object result = proxy.invokeSuper(obj, args);
        //执行后逻辑
       
System.out.println("after---------->");
        return result;
    }
}
第四步:创建工厂类,产生代理实例
/**
 *
代理对象的工厂类,在这里完成切面的封装
 
*/
public class ProxyFactory {
    public static Service getInstance(ServiceProxy proxy) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Service.class);
        enhancer.setCallback(proxy);
        return (Service) enhancer.create();
    }
}
第五步:测试
/**
 *
测试类
 
*/
public class Test {
    public static void main(String[] args) {
        ServiceProxy proxy = new ServiceProxy();
        Service service = ProxyFactory.getInstance(proxy);
        service.add();
        //新生成的类是Service的子类
       
System.out.println(service.getClass().getSimpleName());
System.out.println(( service.getClass().getSuperclass().getSimpleName()));
    }
}
控制台输出:
before--------->
add-------
after---------->
Service$$EnhancerByCGLIB$$10ccd71e
Service
第四章:总结
使用JDK和cglib都可以通过操作Java字节码实现动态代理,JDK动态代理使用接口操作字节码,cglib在ASM框架上进行实现,性能上cglib高于jdk的(没有验证)。JDK动态代理中,被代理类需要有统一的接口,代理类是接口的实现;在cglib的动态代理中,被代理类不需要实现统一的接口,代理类是被代理类的子类。
在Spring AOP中包含了这两种动态代理方法,具体的调用根据被代理类的是否有统一接口决定。

 

posted on 2018-01-08 20:18  Stark_Tan  阅读(142)  评论(0编辑  收藏  举报