静态代理

1.静态代理的角色分析(UML画图推荐使用StarUML软件)

 抽象角色---一般使用接口或者抽象类来实现。

 真实角色---被代理的角色。

代理角色---代理真实角色—代理真是角色后一般会做一些附属操作。

客户-------使用代理角色来进行一些操作.

2.代码的实现(房东-中介-客户)

 Rent.java--抽象角色

package cn.sxt.staticproxy;

public interface Rent {
public void rent();
}

Host.java--真实角色

package cn.sxt.staticproxy;

public class Host implements Rent{
@Override
public void rent(){
System.out.println("房屋出租");
}
}

Proxy.java--代理角色

package cn.sxt.staticproxy;

public class Proxy implements Rent{
private Host host;
public Proxy(){ }
public Proxy(Host host) {
super();
this.host = host;
}
public void setHost(Host host) {
this.host = host;
}
//租房
public void rent(){
seeHouse();
host.rent();
fare();
}
//看房
private void seeHouse(){
System.out.println("带房客看房");
}
//收中介费
private void fare(){
System.out.println("收取中介费");
}
}

Client.java--客户

package cn.sxt.staticproxy;

public class Client {
public static void main(String[] args) { Host host=new Host();
Proxy proxy=new Proxy(host);
proxy.rent();
}
}

3.使用静态代理的好处:

使得真实角色处理的业务更加的纯粹,不再去关注一些公共的事情;

      公共的业务由代理来完成---实现了业务的分工;

      公共业务发生扩展时,变得更加集中和方便;

举例说明:

UserService.java:

public interface UserService {
public void add();
public void update();
public void delete();
public void search();
}

UserServiceImpl.java:关注纯粹的业务逻辑

public class UserServiceImpl implements UserService {

	@Override
public void add() {
System.out.println("增加用户");
} @Override
public void update() { System.out.println("修改用户");
} @Override
public void delete() { System.out.println("删除用户");
} @Override
public void search() { System.out.println("查询用户");
}
}

UserServiceProxy.java:处理一些公共的事务,比如日志

public class UserServiceProxy implements UserService {

	private UserService userService;

	@Override
public void add() {
log("add");
userService.add();
} @Override
public void update() {
log("update");
userService.update();
} @Override
public void delete() {
log("delete");
userService.delete();
} @Override
public void search() {
log("search");
userService.delete();
} public void log(String methodName) {
System.out.println("执行" + methodName + "执行");
} }

静态代理的缺点:

类变的多了---多了代理类,工作量变大了,开发效率降低了

于是乎----动态代理出现了:有静态代理的好处,抛弃静态代理的缺点

动态代理

1.动态代理和静态代理的角色是一样的。

2.动态代理的代理类是动态生成的。

3.动态代理分为两类

a)基于接口的动态代理---jdk动态代理

b)基于类的动态代理---cglib

现在用javasist来生成动态代理

4.jdk的动态代理---Proxy类和InvocationHandler接口

InvocationHandler 是代理实例的调用处理程序 实现的接口。

每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。

invoke方法:

Object invoke(Object proxy, Method method, Object[] args)
          在代理实例上处理方法调用并返回结果。

在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。

参数:
proxy - 在其上调用方法的代理实例
method - 对应于在代理实例上调用的接口方法的 Method 实例。Method 对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。
args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。基本类型的参数被包装在适当基本包装器类(如 java.lang.Integerjava.lang.Boolean)的实例中。
返回:
从代理实例的方法调用返回的值。如果接口方法的声明返回类型是基本类型,则此方法返回的值一定是相应基本包装对象类的实例;否则,它一定是可分配到声明返回类型的类型。如果此方法返回的值为 null 并且接口方法的返回类型是基本类型,则代理实例上的方法调用将抛出 NullPointerException。否则,如果此方法返回的值与上述接口方法的声明返回类型不兼容,则代理实例上的方法调用将抛出 ClassCastException

Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
          返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。

返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。此方法相当于:

     Proxy.getProxyClass(loader, interfaces).
getConstructor(new Class[] { InvocationHandler.class }).
newInstance(new Object[] { handler });

Proxy.newProxyInstance 抛出 IllegalArgumentException,原因与 Proxy.getProxyClass 相同。

参数:
loader - 定义代理类的类加载器
interfaces - 代理类要实现的接口列表
h - 指派方法调用的调用处理程序

实现:

public class ProxyInvocationHandler implements InvocationHandler{
//目标对象--真实对象
private Object target;
public void setTarget(Object target) {
this.target = target;
}
/**
* 生成代理类:
*/
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
} /**
* proxy--是代理类
* method--代理类的实例(proxy)调用的处理程序(add)的方法对象
* 比如调用proxy.add():此处method.getName就是add
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
log(method.getName());
Object result=method.invoke(target, args);
return result;
}
public void log(String methodName){
System.out.println("执行"+methodName+"方法");
}
//看房
private void seeHouse(){
System.out.println("带房客看房");
}
//收中介费
private void fare(){
System.out.println("收取中介费");
} }

Client:

import cn.sxt.service.UserService;
import cn.sxt.service.UserServiceImpl; public class Client {
public static void main(String[] args) { UserService userService=new UserServiceImpl();
ProxyInvocationHandler pih=new ProxyInvocationHandler();
pih.setTarget(userService);
UserService proxy=(UserService)pih.getProxy();
proxy.add();
}
}

一个动态代理一般代理某一类业务,一个动态代理可以代理多各类

Spring学习笔记--代理的更多相关文章

  1. Spring学习笔记之aop动态代理(3)

    Spring学习笔记之aop动态代理(3) 1.0 静态代理模式的缺点: 1.在该系统中有多少的dao就的写多少的proxy,麻烦 2.如果目标接口有方法的改动,则proxy也需要改动. Person ...

  2. 不错的Spring学习笔记(转)

    Spring学习笔记(1)----简单的实例 ---------------------------------   首先需要准备Spring包,可从官方网站上下载.   下载解压后,必须的两个包是s ...

  3. Spring学习笔记(一)

    Spring学习笔记(一) 这是一个沉淀的过程,大概第一次接触Spring是在去年的这个时候,当初在实训,初次接触Java web,直接学习SSM框架(当是Servlet都没有学),于是,养成了一个很 ...

  4. 【Spring学习笔记-MVC-3.1】SpringMVC返回Json数据-方式1-扩展

    <Spring学习笔记-MVC>系列文章,讲解返回json数据的文章共有3篇,分别为: [Spring学习笔记-MVC-3]SpringMVC返回Json数据-方式1:http://www ...

  5. spring学习笔记(一) Spring概述

    博主Spring学习笔记整理大部分内容来自Spring实战(第四版)这本书.  强烈建议新手购入或者需要电子书的留言. 在学习Spring之前,我们要了解这么几个问题:什么是Spring?Spring ...

  6. Java框架spring 学习笔记(十八):事务管理(xml配置文件管理)

    在Java框架spring 学习笔记(十八):事务操作中,有一个问题: package cn.service; import cn.dao.OrderDao; public class OrderSe ...

  7. Spring学习笔记2——表单数据验证、文件上传

    在上一章节Spring学习笔记1——IOC: 尽量使用注解以及java代码中,已经搭建了项目的整体框架,介绍了IOC以及mybatis.第二节主要介绍SpringMVC中的表单数据验证以及文件上传. ...

  8. 【Spring学习笔记-MVC-15.1】Spring MVC之异常处理=404界面

    作者:ssslinppp       异常处理请参考前篇博客:<[Spring学习笔记-MVC-15]Spring MVC之异常处理>http://www.cnblogs.com/sssl ...

  9. 【Spring学习笔记-MVC-13.2】Spring MVC之多文件上传

    作者:ssslinppp       1. 摘要 前篇文章讲解了单文件上传<[Spring学习笔记-MVC-13]Spring MVC之文件上传>http://www.cnblogs.co ...

随机推荐

  1. Session.Abandon和Session.Clear的实现和区别

    我在网上找了一个比较贴切的描述: Session.Clear()就是把Session对象中的所有项目都删除了,Session对象里面啥都没有.但是Session对象还保留.Session.Abando ...

  2. Ubuntu中安装和配置 Java JDK,并卸载自带OpenJDK(以Ubuntu 14.04为例)

    1.下载jdk-7u67-linux-x64.tar.gz 2.用ftp客户端工具filezilla上传到ubuntu的合适文件夹.如果如果不能上传到指定文件夹可能是文件夹权限不足,修改文件夹可执行权 ...

  3. excel随机函数

    =D7+RAND()*(8000-4250) 含义: 1.在D7数值的基础上,随机加一个数值,该数值的随机范围为4250——8000. 2.注意8000和4250要反着写

  4. Mac下用zsh

    最近好多实验要跑,有时候Finder切换来切换去,感觉还不如用terminal. Mac默认的shell是bash.所以说我其实今天才弄明白shell和terminal之间的关系.在人和计算机内核之间 ...

  5. 【转载】js关闭当前页面(窗口)的几种方式总结

    1. 不带任何提示关闭窗口的js代码 复制代码代码如下: <a href="javascript:window.opener=null;window.open('','_self'); ...

  6. 4S店的潜规则内幕曝光

  7. Python验证码识别 安装Pillow、tesseract-ocr与pytesseract模块的安装以及错误解决

    1.安装Pillow pip install Pillow 2.安装tesseract-ocr OCR(Optical Character Recognition, 光学字符识别) 软件 安装包含两个 ...

  8. 开源CFD并非万金油

    今天有网友在群里讨论开发CFD软件的事情,众说纷纭,有网友提到"没有必要开发CFD软件了,直接使用开源OpenFOAM就行".但个人认为这说法还是有一些需要商榷的地方,开源软件也不 ...

  9. 20款最好的jQuery文件上传插件

    当它是关于开发网络应用程序和网页的时候,文件上传功能的重要性是不容忽视的.一个文件上传功能可以让你上传所有类型的文件在网站上,包括视频,图像,文件和更多.创建一个文件上传功能,对你的网站是不是很难,有 ...

  10. 【iCore1S 双核心板_ARM】例程十一:RTC实时时钟实验——显示时间和日期

    实验现象: 核心代码: int main(void) { /* USER CODE BEGIN 1 */ RTC_DateTypeDef sDate; RTC_TimeTypeDef sTime; u ...