Java静态代理和动态代理
Java代理简介
Java中的代理通常是为某个对象提供一种代理机制,从而控制对这个对象不能直接进行访问,代理不是技术而是一种设计模式。
代理机制能够实现对某个对象业务功能实现的隐藏,代理程序可以对目标对象进行渲染以及对使用对象者进行有效控制,代理可以被看做是AOP模式的实现。
代理实现中可以分为以下角色:
抽象接口:声明真实对象和代理对象的共同接口
代理角色(代理实现者):其中主要包含了被代理对象
真实角色(被代理对象):客户最终要引用目标对象
静态代理实现
- 代理角色和真实角色拥有共同的抽象接口
- 一个真实对象对应一个代理角色
- 真实角色实现必需存在,在代理对象中被固定不变
- 设计实现简单清晰,会产生更多的类
动态代理实现
- 代理类的代理实现代码被固定下来,不会因为业务的逐渐增长的改变
- 在程序运行时才确定被代理对象类型
- 实现AOP编程更加灵活,这是静态代理无法实现的
- 解耦,如果用在web业务下,可以实现数据层和业务层的
InvocationHandler组件
InvocationHandler是java.lang.reflect反射包下的实现动态代理的规范接口,通常自定义实现的动态代理类必须实现此接口。
Object invoke(Object obj,Method method,Object[] args)
参数obj是动态代理实现的实例
参数method是目标被代理对象的业务方法
参数args是传递给目标方法的所有参数
Object是目标方法的返回值,如果没有返回值则返回null对象
Proxy组件
java.lang.reflect.Proxy类提供了用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler handler)
参数loader是被代理类的类加载器
参数interfaces是被代理类的所有父接口
参数handler是实现动态代理类的实例
静态代理:
package com.xzit.entity; /** * 客户实体类 * @author Administrator * */ public class Client { private String name; // 客户姓名 private boolean isVip; // 是否是VIP客户 public String getName() { return name; } public void setName(String name) { this.name = name; } public boolean isVip() { return isVip; } public void setVip(boolean isVip) { this.isVip = isVip; } }
package com.xzit.entity; /** * 商品实体类 * @author Administrator * */ public class Goods { private String number;// 商品编号 private String name;// 商品名称 private Double price; // 商品单价 public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Double getPrice() { return price; } public void setPrice(Double price) { this.price = price; } public Goods() { } public Goods(String number, String name, Double price) { this.number = number; this.name = name; this.price = price; } }
package com.xzit.entity; import com.xzit.db.DataBase; import com.xzit.interfaces.IGoods; import java.util.List; /** * 生产商 */ public class Producer implements IGoods { @Override public List<Goods> producerGoodsList() { return DataBase.GOODSLIST; } }
package com.xzit.interfaces; import com.xzit.entity.Goods; import java.util.List; /** * 提供产品列表的接口 * 代理实现者和被代理对象都应该实现此接口 */ public interface IGoods { /** * 提供产品的方法 * @return */ List<Goods> producerGoodsList(); }
package com.xzit.aop; import com.xzit.entity.Client; import com.xzit.entity.Goods; import com.xzit.entity.Producer; import com.xzit.interfaces.IGoods; import java.util.List; public class ProducerProxy implements IGoods { private Producer producer; //被代理对象 private Client client; //购买对象 @Override public List<Goods> producerGoodsList() { boolean bool = validateIsVip(); if (bool){ List<Goods> goodsList = producer.producerGoodsList(); for (Goods g:goodsList){ g.setPrice(g.getPrice()*0.85); } return goodsList; } return producer.producerGoodsList(); } public void setProducer(Producer producer) { this.producer = producer; } public void setClient(Client client) { this.client = client; } private boolean validateIsVip(){ if (client.isVip()) return true; return false; } }
package com.xzit.proxy; import com.xzit.aop.ProducerProxy; import com.xzit.entity.Client; import com.xzit.entity.Goods; import com.xzit.entity.Producer; import java.util.List; import java.util.Scanner; public class TestStaticProxy { public static void main(String[] args) { Scanner in = new Scanner(System.in); ProducerProxy proxy = new ProducerProxy(); //代理实现者 proxy.setProducer(new Producer()); System.out.println("输入客户姓名"); String name = in.next(); System.out.println("您是VIP请输入1,否则输入0"); int isVip = in.nextInt(); boolean bool = isVip == 1?true:false; Client c = new Client(); c.setName(name); c.setVip(bool); proxy.setClient(c); List<Goods> goodsList = proxy.producerGoodsList(); //调用代理实现方法 for (Goods g:goodsList){ System.out.println(g.getName()+"\t"+g.getNumber()+"\t"+g.getPrice()); } } }
package com.xzit.db; import java.util.ArrayList; import java.util.List; import com.xzit.entity.Department; import com.xzit.entity.Employee; import com.xzit.entity.Goods; public class DataBase { public static final List<Department> DEPLIST = new ArrayList<Department>(); public static final List<Employee> EMPLIST = new ArrayList<Employee>(); public static final List<Goods> GOODSLIST = new ArrayList<Goods>(); static{ DEPLIST.add(new Department("dep100","事业部")); DEPLIST.add(new Department("dep200","策划部")); DEPLIST.add(new Department("dep300","市场部")); DEPLIST.add(new Department("dep400","人事部")); DEPLIST.add(new Department("dep500","研发部")); DEPLIST.add(new Department("dep600","测试部")); EMPLIST.add(new Employee("任我行","男","黑木崖")); EMPLIST.add(new Employee("任盈盈","女","黑木崖")); EMPLIST.add(new Employee("令狐冲","男","华山")); EMPLIST.add(new Employee("岳不群","男","华山")); EMPLIST.add(new Employee("丁春秋","男","南海")); GOODSLIST.add(new Goods("goods100","加热器",123.50)); GOODSLIST.add(new Goods("goods200","胜利羽毛球lark4",54.00)); GOODSLIST.add(new Goods("goods300","联想笔记本T450",8900.50)); GOODSLIST.add(new Goods("goods400","小米麦克风",99.50)); } }
---------------------------------------------------------分割线---------------------------------------------------------------
动态代理:
package com.xzit.entity; /** * 部门信息实体类 * @author Administrator * */ public class Department { private String number;// 部门编号 private String name;// 部门名称 public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Department() { } public Department(String number, String name) { this.number = number; this.name = name; } }
package com.xzit.entity; /** * 员工实体类 * @author Administrator * */ public class Employee { private String name; private String sex; private String address; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } /** * 无参构造器 */ public Employee() { } /** * 有参构造器 * @param name * @param sex * @param address */ public Employee(String name, String sex, String address) { this.name = name; this.sex = sex; this.address = address; } }
package com.xzit.interfaces; import java.util.List; public interface IObject<T> { /** * 查找目标数据列表 * @return */ List<T> findList(); }
package com.xzit.interfaces; import com.xzit.db.DataBase; import java.util.List; public class DepartmentDaoImp<T> implements IObject<T>{ @Override public List<T> findList() { System.out.println("获取部门列表"); return (List<T>) DataBase.DEPLIST; } }
package com.xzit.interfaces; import com.xzit.db.DataBase; import java.util.List; public class EmployeeDaoImp<T> implements IObject<T>{ @Override public List<T> findList() { System.out.println("获取员工列表"); return (List<T>) DataBase.EMPLIST; } }
package com.xzit.aop; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class DynInvoke implements InvocationHandler { private Object target; //被代理的对象 /** * 重写实现动态代理的invoke方法 * @param proxy * @param arg1 * @param arg2 * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method arg1, Object[] arg2) throws Throwable { System.out.println("动态代理方法"); Object obj = arg1.invoke(target,arg2); return obj; } public void setTarget(Object target){ this.target = target; } }
package com.xzit.proxy; import com.xzit.aop.DynInvoke; import com.xzit.entity.Department; import com.xzit.entity.Employee; import com.xzit.interfaces.DepartmentDaoImp; import com.xzit.interfaces.EmployeeDaoImp; import com.xzit.interfaces.IObject; import java.lang.reflect.Proxy; import java.util.List; public class TestDynProxy { /** * 动态代理测试 * @param args */ public static void main(String[] args) { DynInvoke dynInvoke = new DynInvoke(); //创建动态代理对象 DepartmentDaoImp<Department> depDao = new DepartmentDaoImp<Department>(); //创建被代理的目标对象 EmployeeDaoImp<Employee> empDao = new EmployeeDaoImp<Employee>(); dynInvoke.setTarget(depDao); //设置被代理对象 dynInvoke.setTarget(empDao); //设置被代理对象 Class [] classes = depDao.getClass().getInterfaces(); //获取所有被代理对象的父接口数组 IObject iObject = (IObject) Proxy.newProxyInstance(empDao.getClass().getClassLoader(),classes,dynInvoke); //获取代理类实例 List<Employee> depList = iObject.findList(); //调用目标方法 for (Employee dep:depList){ System.out.println(dep.getName()); } } }