静态代理

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. 1.Linux进程--进程标识号

    函数原型 pid_t fork(void); fork的奇异之处在于它被调用一次,却返回两次,它可能有三种不同的返回值: 1.在父进程中.fork返回新创建的子进程的PID 2.在子进程中,fork返 ...

  2. 【.NET线程--进阶(一)】--线程方法详解

    上篇博客从线程的基本概况开始着重讨论了线程,进程,程序之间的区别,然后讨论了线程操作的几个类,并通过实例来说明了线程的创建方法.本篇博客将会带大家更深入的了解线程,介绍线程的基本方法,并通过一个Dem ...

  3. html5调用手机陀螺仪实现方向辨识

    获取移动设备的陀螺仪,需要知道陀螺仪包含什么. 我们可以让document监听deviceorientation 来获取相关的数据,里面包括3个值 alpha.beta和gamma. 这三个值分别代表 ...

  4. linux下安装python dlib依赖

    dlib是主要用于机器学习的库,封装了机器学习算法,可以非常方便的实现比如人脸识别,车辆识别,物体检测以其他很多功能,dlib默认使用C++进行开发,另外图像识别有一部分支持python接口开发,上手 ...

  5. WIN10平板系统 如何自定义分辨率,修改分辨率

    从以下网址下载Intel网卡驱动,注意只要下载zip版本的(如果是exe版本的,双击将提示win10无法为此计算机验证正在安装的驱动程序,也包括你用驱动精灵这种软件,也会安装的时候由于这个问题装不上) ...

  6. 使用SpringBoot配置了 server.servlet.path后无效的解决方案

    一.问题描述 使用SpringBoot配置了 server.servlet.path后无效,访问时无法通过:http://127.0.0.1:8080/app/hello.html 访问. 二.解决方 ...

  7. 访问 Google

    对于一个技术人员访问Google是何其的重要呀? 一下收集了一些访问的连接,不愿意使用VPS的同学可以使用下: 非原版: Glgoo:http://www.glgoo.com/九尾搜索:http:// ...

  8. ORA-19602: cannot backup or copy active file in NOARCHIVELOG mode

    备份数据库,报错如下 RMAN> backup database; Starting backup at -JAN- allocated channel: ORA_DISK_1 channel ...

  9. java 除法运算只保留整数位的3种方式

      1.情景展示 根据提供的毫秒数进行除法运算,如果将毫秒数转换成小时,小时数不为0,则只取整数位,依此类推... 2.情况分析 可以使用3个函数实现 Math.floor(num)  只保留整数位 ...

  10. tar加密

    # tar -czvf - file_name|openssl des3 -salt -k |dd of=file_name.des3 # ls flie_name file_name.des3 # ...