Java动态代理知识

切面:  包括切点和增强,切点是执行点的表示,增强包括增强逻辑代码和方位信息,其实增强也是一个一般的切面,只是此切面针对所有类的所有方法。(Spring目前只支持方法级别的增强)

两种动态代理实现切面技术

           1.JDK动态代理  主要针对接口类型数据

                 把横切代码安置在MyInnovacationHandler中                

public class MyInnovacationHandler implements InvocationHandler {

    private Waiter waiter;
//设置要调用的对象
public MyInnovacationHandler(Waiter waiter) { this.waiter = waiter; } @Override
// proxy表示代理对象 method表示要代理的方法 args表示目标方法参数
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("模拟调用 how are you " + args[0]);
//调用目标对象 Object object
= method.invoke(waiter, args); return object; } }

 

    调用JDK动态代理的代码

public static void textJDKProxy() {
//Waiter 表示接口 Waiter waiter
= new NaviWaiter(); MyInnovacationHandler handler = new MyInnovacationHandler(waiter); Waiter proxy = (Waiter) Proxy.newProxyInstance(waiter.getClass().getClassLoader(), waiter.getClass().getInterfaces(), handler); proxy.greetTo("张"); proxy.serveTo("刘"); }

 

          2. CGLIB动态代理技术:针对类数据代理,采用底层字节码技术,可以为一个类创建子类,在子类中采用拦截的技术拦截所有父类方法的调用 并顺势织入横切逻辑。

             代理创建对象代码如下

public class CGlibProxy implements MethodInterceptor {
    private Enhancer enhancer = new Enhancer();

    public Object getProxy(Class clazz) {
//        设置父类的字节码
        enhancer.setSuperclass(clazz);
//        设置使用本对象的invoke方法
        enhancer.setCallback(this);
//        通过字节码技术动态创建子类实例
        return enhancer.create();
    }

    /**
     * @param o           表示目标类的实例
     * @param method      目标类方法的反射对象
     * @param objects     d动态入参数
     * @param methodProxy 方法代理
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//        织入横切代码
        PerFormanceMonitor.begin(o.getClass().getName() + "." + method.getName());
//        调用目标方法
        Object object = methodProxy.invokeSuper(o, objects);
        //  织入横切代码
        PerFormanceMonitor.end();
        return object;
    }
}

 

    调用代码

public static void proxy2() {
         //创建CGlibProxy代理对象
        CGlibProxy cGlibProxy = new CGlibProxy();
//获得代理对象 其实就是此类的子类 ForumServiceImpl forumService
= (ForumServiceImpl) cGlibProxy.getProxy(ForumServiceImpl.class);
//调用方法 forumService.removeFrume(
10); forumService.removeTopic(10); }

 

      注意:      两种动态代理方法的区别:JDK代理只针对接口类型数据,此中方法创建代理对象比CGlibProxy快,但代理对象的性能没有CGlibProxy方式高,所以在对象创建不频繁时(即sigleton),建议使用CGlibProxy方式实现动态代理.

          针对CGlibProxy方式,只是通过创建子类的方式实现,因此对于Final类型类或具有final变量的类而言,这就容易出现问题。所以并非所有对象都能创建代理

 

posted @ 2017-11-08 21:51  张秀杰  阅读(230)  评论(0编辑  收藏  举报