有时目标对象不可直接访问,只能通过代理对象访问
图示:


面向接口编程
静态代理对象代码
- package com.example.service.impl;
-
- import com.example.service.Service;
-
- public class Agent implements Service {
-
- //定义接口对象
- public Service target;
-
- public Agent(){}
-
- //传入接口对象
- public Agent(Service target){
- this.target = target;
- }
-
- @Override
- public void sing() {
- System.out.println("协商演出时间......");
- System.out.println("协商演出地点......");
-
- //目标对象完成核心业务,接口指向实现类,调用实现类的方法
- target.sing();
-
- System.out.println("协商演出费用......");
- }
- }
位于:java.lang.reflect.Proxy包下
有一个核心方法:Proxy.newProxyInstance(....),专门获取动态代理对象,有三个参数
参数1:ClassLoader loader
参数2:Class>[] interfaces
上面两个参数为代理对象动态的创建和调用目标对象的方法提供了数据支持,第3个参数相当于调用程序
参数3:InvocationHandler
- new InvocationHandler() {
- @Override
- public Object invoke(
- Object obj,
- //用来反射调用方法
- Method method,
- //待调用方法需要的参数
- Object[] args)
- throws Throwable {
-
- //扩展业务
- System.out.println("协商演出时间......");
- System.out.println("协商演出地点......");
-
- //核心业务,具体调用什么方法根据外层业务来反射调用对应方法
- Object res = method.invoke(target, args);
-
- //扩展业务
- System.out.println("协商演出费用......");
-
- //目标对象执行的目标方法的返回值
- return res;
- }
- }
代理工厂代码
- package com.example.proxy;
-
- import com.example.service.Service;
-
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
-
- public class ProxyFactory {
- //目标对象
- Service target;
-
- public ProxyFactory(){}
-
- public ProxyFactory(Service target){
- this.target = target;
- }
-
- //返回代理对象
- public Object getAgent(){
- return Proxy.newProxyInstance(
- //需要知道受代理对象的类信息
- target.getClass().getClassLoader(),
- //需要知道受代理对象实现的所有接口信息
- target.getClass().getInterfaces(),
- //反射调用目标对象的目标方法
- new InvocationHandler() {
- @Override
- public Object invoke(
- Object obj,
- //用来反射调用方法
- Method method,
- //待调用方法需要的参数
- Object[] args)
- throws Throwable {
-
- //扩展业务
- System.out.println("协商演出时间......");
- System.out.println("协商演出地点......");
-
- //核心业务,具体调用什么方法根据外层业务来反射调用对应方法
- Object res = method.invoke(target, args);
-
- //扩展业务
- System.out.println("协商演出费用......");
-
- //目标对象执行的目标方法的返回值
- return res;
- }
- }
- );
- }
- }
测试代码示例
- package com.example.proxy;
-
- import com.example.service.Service;
- import com.example.service.impl.SuperStarZhou;
- import org.junit.Test;
-
- public class TestProxyFactory {
- @Test
- public void testGetProxy(){
- //确定客户需求
- ProxyFactory factory = new ProxyFactory(new SuperStarZhou());
- //根据需求动态返回对应类型的代理对象
- Service agent = (Service) factory.getAgent();
- //依托对应类型的动态代理对象完成业务:扩展业务(动态代理对象完成) + 核心业务(目标对象完成)
- agent.sing();
- }
-
- @Test
- public void testGetProxy2(){
- ProxyFactory factory = new ProxyFactory(new SuperStarZhou());
- Service agent = (Service) factory.getAgent();
- String res = (String) agent.show(60);
- System.out.println(res);
- }
- }
可被代理的方法应该是受代理对象实现的所有接口中的方法与其所有实体方法的交集
类型的转变
- @Test
- public void testGetProxy2() {
- ProxyFactory factory = new ProxyFactory(new SuperStarZhou());
- Service agent = (Service) factory.getAgent();
- Service liu = new SuperStarLiu();
- System.out.println("类型1: " + liu.getClass());
- System.out.println("类型2: " + agent.getClass());
- }
- /*
- 输出结果:
- 类型1: class com.example.service.impl.SuperStarLiu
- 类型2: class com.sun.proxy.$Proxy7
- */