为了账号安全,请及时绑定邮箱和手机立即绑定

国际富邦在线,永利百家乐

2016.07.30 10:14 3995浏览

本文地址:http://www.bgel.cn/article/11299
文章摘要:国际富邦在线,永利百家乐,真钱博彩,扎金花棋牌游戏官网

在Spring中,严格的来说不单单使用JDK的动态代理,还会使用CGLIB动态代理,但是它们大同小异,我们这里讲JDK的动态代理,有了它的理解CGLIB也不难掌握,读者可以阅读其他的文档。

这篇文章是揭示Spring AOP原理的基础,是所有章节中的重点内容之一,初学者需要认真学习和掌握它,否则后面讲解会很难理解的,一定多多敲代码体会它,你的进步就会很大

首先,让我们先了解什么是动态代理,假设读者是一个软件工程师,而你的公司是家软件公司,我是一个客户,我需要你公司提供软件的专业服务。显然我是找到你们公司的商务,而不是你去讨论我的要求。那么商务就等同于你的一个代理,我也会认为商务等于你们公司,而不会去管你这个软件工程师如何工作的。

代理的实际就是在真实服务对象(软件工程师)之前加多一个占位或者叫做代理对象(商务),这个占位(商务)可以根据调用者(客户)的要求去控制真实服务对象的访问(软件工程师)。有了这个比喻是不是好理解很多??

那么代理模式的好处在于什么?首先占位(商务)可以在真实服务对象之前之后做一些服务,同时根据需要选择是否需要启用真实服务对象,也会加入一些规则,比如商务也可以根据客户和公司的规则来提供额外的服务,这时可能就连真实服务对象(软件工程师)都不会启用。

好,上面的东西貌似很神奇,我们用一张图来表达代理的含义。

图片描述

好,这里的代理对象就是我们之前谈到的占位,它代理了我们看到的真实对象,可以在真实对象之前之后,甚至是代替真实对象提供服务。

动态代理有好几种,Spring使用了CGLIG和JDK动态代理。在JDK动态代理中,要求必须提供接口,而CGLIB是不需要的,我们这里只谈论JDK动态代理,在大部分的情况下,笔者建议你使用JDK动态代理,因为JDK动态代理的速度要比CGLIB要快,在Spring中一个有切面的Bean如果有接口声明,Spring就会用JDK动态代理代理它,否者启用CGLIB。

好了论述讲了一大截,我们开始讲JDK动态代理,首先我们需要提供一个简单的接口:

package com.learn.chapter1.proxy;
/**
 *
 * @author ykzhen2015
 */
public interface HelloService {
    public void sayHello(String name);
}

跟着是实现类:

package com.learn.chapter1.proxy;

/**
 *
 * @author ykzhen2015
 */
public class HelloServiceImpl implements HelloService {

    @Override
    public void sayHello(String name) {
        System.err.println("hello " + name);
    }

}

好都很简单,不需要笔者做任何解释。我们跟着就是要生成代理对象(proxy),分成两步:

  • 生成代理对象要建立代理对象(proxy)和真实对象(HelloServiceImpl)的代理关系。
  • 实现代理方法
    在JDK动态代理中需要实现接口:java.lang.reflect.InvocationHandler。让我们先来看看它:
package com.learn.chapter1.proxy;

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

/**
 *
 * @author ykzhen2015.
 */
public class HelloProxy implements InvocationHandler {

    private Object target;

    /**
     * 生成代理对象,并和真实服务对象绑定.
     * @param target 真实服务对线下 
     * @return 代理对象
     */
    public Object bind(Object target) {
        this.target = target;
        //生成代理对象,并绑定.
        Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), //类的加载器
                target.getClass().getInterfaces(), //对象的接口,明确代理对象挂在哪些接口下
                this);//指明代理类,this代表用当前类对象,那么就要求其实现InvocationHandler接口
        return proxy;
    }

    /**
     * 当生成代理对象时,第三个指定使用HelloProxy进行代理时,代理对象调用的方法就会进入这个方法。
     * @param proxy ——代理对象
     * @param method -- 被调用的方法
     * @param args -- 方法参数
     * @return  代理方法返回。
     * @throws Throwable  -- 异常处理
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.err.println("反射真实对象方法前");
        Object obj = method.invoke(target, args);//相当于sayHello方法调用.
        System.err.println("反射真实对象方法后");
        return obj;
    }

}

好了,有了上面的代码我们论述一下(实际注释也很清晰),

  • 首先声明了一个类的属性target,它的作用是保存真实服务对象(软件工程师)。
  • 然后用bind方法绑定代理对象(proxy 商务)和真实对象(软件工程师),是通过这样去绑定的:

Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), //类的加载器
target.getClass().getInterfaces(), //对象的接口,明确代理对象挂在哪些接口下
this);//指明代理类,this代表用当前类对象,那么就要求其实现InvocationHandler接口的invoke方法,而代理逻辑就放入invoke方法里。
用之前的比喻就是proxy就是商务,它代理了target这个软件工程师,而商务代理的逻辑方法放在this这个对象的invoke方法里,只是this这个对象需要实现InvocationHandler接口而已。

  • 这样声明就会进入当前类invoke方法,它实现的是代理逻辑(按比喻就是商务逻辑)它有三个参数:

Object proxy ——当前代理对象(商务)
Method method —— 当前调度的方法
Object[] args -- 方法参数

然后我们通过反射调度真实对象的方法,不懂的可以看到第一篇的论述(扎金花棋牌游戏官网
Object obj = method.invoke(target, args);//相当于sayHello方法调用.

让我们测试一下这段代码:

package com.learn.chapter1.main;

import com.learn.chapter1.pojo.Role;
import com.learn.chapter1.proxy.HelloProxy;
import com.learn.chapter1.proxy.HelloService;
import com.learn.chapter1.proxy.HelloServiceImpl;
import com.learn.chapter1.utils.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.Transaction;

/**
 *
 * @author ykzhen2015
 */
public class Chapter1Main {

    public static void main(String[] args) {
       HelloProxy helloProxy = new HelloProxy();
       //因为使用了接口HelloService绑定了代理对象,所以可以用HelloService作为代理对象的声明.
       HelloService proxy = (HelloService) helloProxy.bind(new HelloServiceImpl());
       proxy.sayHello("张三");//此时使用代理对象运行方法进入HelloProxy的invoke方法里
    }
}

这和时候,我们运行一下可以得到下面的打印:

反射真实对象方法前
hello 张三
反射真实对象方法后

好了,我们看到的HelloService实际已经是一个代理对象了,而不是我们普通人看到的HelloServiceImpl这个真实对象,在Spring中不要被它迷糊了哦。

这篇很重要,是我们以后的基础,所以笔者也论述得比较详细,希望大家好好学习,一定要多敲代码,好好体会哦。

点击查看更多内容

本文原创发布于慕课网 ,转载请注明出处,谢谢合作

36人点赞

若觉得本文不错,就分享一下吧!

评论

相关文章推荐

正在加载中
意见反馈 去赚学费 帮助中心 APP下载
官方微信
扎金花棋牌游戏官网

举报

0/150
提交
取消
网站地图 a8娱乐城 拉斯维加斯赌场网址 天天娱乐软件 金沙城APP
龙8手机app下载安装 皇浦国际
邮箱 大奖娱乐 吉历娱乐 世界球国家队排行
亚虎国际app 亚虎国际app 龙8APP下载 凤凰官网手机网
金花棋牌游戏 求万博体育官网 天时娱乐下载 亚博体育无法注册
678彩票网官网 圣亚娱乐登陆 亿游娱乐平台 丰尚娱乐 丰尚娱乐彩票
天下彩 银豹娱乐登陆 鸿鑫娱乐 爱购彩平台 圣亚娱乐会员
汇丰娱乐在线 亚洲最大彩票平台 j8彩票网 大神娱乐官方网站 天空彩票宝典
天游娱乐注册 捷豹365彩票登录 汇丰在线注册 98彩票网手机版 快彩代理平台