静态代理设计模式
基本概念
通过代理类的对象,为原始类的对象(目标类的对象)添加辅助功能,更容易更换代理实现类、利于维护。
静态代理 |
---|
优缺点
- 代理类 = 实现原始类相同接口 + 添加辅助功能 + 调用原始类的业务方法。
- 静态代理的问题
- 代理类数量过多,不利于项目的管理。
- 多个代理类的辅助功能代码冗余,修改时,维护性差。
代码实例
Business 业务接口
package com.qianfeng.workone.example.dynamic;
public interface Business {
void sing(String singName);
void dance();
Integer price(int price);
}
Actor演员类
package com.qianfeng.workone.example.dynamic;
public class Actor implements Business{
@Override
public void sing(String singName) {
System.out.println("在舞台上面唱" + singName);
}
@Override
public void dance() {
System.out.println("在舞台上尽情跳舞");
}
@Override
public Integer price(int price) {
System.out.println("结算薪资是" + price);
return price;
}
}
Bbroker经纪人类
package com.qianfeng.workone.example.dynamic;
public class Broker implements Business{
private Actor actor;
public Broker() {
}
public Broker(Actor actor) {
this.actor = actor;
}
@Override
public void sing(String singName) {
System.out.println("经纪人在外谈好活动");
actor.sing(singName);
System.out.println("经纪人在内做好后续工作");
}
@Override
public void dance() {
System.out.println("经纪人在外谈好活动");
actor.dance();
System.out.println("经纪人在内做好后续工作");
}
@Override
public Integer price(int price) {
System.out.println("经纪人在外谈好活动");
Integer price1 = actor.price(price + 5000);
System.out.println("经纪人在内做好后续工作");
return price1;
}
}
Test测试类
package com.qianfeng.workone.example.dynamic;
public class Test {
public static void main(String[] args) {
Actor actor = new Actor();
Broker broker = new Broker(actor);
broker.sing("征服");
broker.dance();
broker.price(10000);
}
}
运行结果
JDK动态代理
基本概念
动态创建代理类的对象,为原始类的对象添加辅助功能。
在原有的静态代理基础上,功能相同但是不被接口中方法中数量所限制,能够动态的在方法前后添加辅助功能
优缺点
在之前的静态代理的基础上可以发现,
有如下规律:在代理类中被代理类的对象方法的前后处理都相同,出现的大量的代码冗余。
在动态代理中内部通过反射的方式将前后处理动态的加载到每一个代理类方法的前后,不被方法的个数和类型所限制。
缺陷就是代理类必须要实现接口
代码实例
Business 业务接口
package com.qianfeng.workone.example.dynamic;
public interface Business {
void sing(String singName);
void dance();
Integer price(int price);
}
Actor演员类
package com.qianfeng.workone.example.dynamic;
public class Actor implements Business{
@Override
public void sing(String singName) {
System.out.println("在舞台上面唱" + singName);
}
@Override
public void dance() {
System.out.println("在舞台上尽情跳舞");
}
@Override
public Integer price(int price) {
System.out.println("结算薪资是" + price);
return price;
}
}
ProxyFactory 代理类的工厂
package com.qianfeng.workone.example.dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyFactory {
public static Object proxy(Object obj){
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("经纪人在外谈好活动");
Object invoke = method.invoke(obj, args);
System.out.println("经纪人在内做好后续工作");
return invoke;
}
});
}
//通过方法泛型的方式能够避免强制类型转换
public static <T> T proxyObject(T obj){
return (T)Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("经纪人在外谈好活动");
Object invoke = method.invoke(obj, args);
System.out.println("经纪人在内做好后续工作");
return invoke;
}
});
}
}
ProxyTest 测试类
package com.qianfeng.workone.example.dynamic;
import com.sun.xml.internal.bind.v2.model.core.EnumLeafInfo;
public class ProxyTest {
public static void main(String[] args) {
Actor actor = new Actor();
ProxyFactory proxyFactory = new ProxyFactory();
Business proxy = (Business) proxyFactory.proxy(actor);
proxy.sing("征服");
proxy.dance();
proxy.price(15000);
System.out.println("=================以下为泛型的使用方式,通用性更好==================");
Business proxyObject = proxyFactory.proxyObject(actor);
proxyObject.sing("动物世界");
proxyObject.dance();
proxyObject.price(18000);
}
}
结果截图
CGLIB动态代理
基本概念
跟jdk原生的动态代理没有什么区别
优缺点
在JDK的基础上能够实现没有实现接口也能够动态代理一个类
代码实例
Actor 被代理类
package com.qianfeng.workone.example.dynamiciscglib;
public class Actor{
public void sing(String singName) {
System.out.println("在舞台上面唱" + singName);
}
public void dance() {
System.out.println("在舞台上尽情跳舞");
}
public Integer price(int price) {
System.out.println("期望薪资是" + price);
return price;
}
}
ProxyFactor 在此类中处理代理类中的细节(取名不严谨)
package com.qianfeng.workone.example.dynamiciscglib;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class ProxyFactory implements MethodInterceptor {
private Actor actor = new Actor();
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//其中o代表被代理类本身,method代表被代理类的响应方法,objects代表被代理类传入的参数,MethodProxy暂不清楚,但是要这要用
System.out.println("代理类的准备工作");
//调用方法一
Object obj = methodProxy.invokeSuper(o, objects);
//调用方法二
Object obj = method.invoke(actor,objects);
System.out.println("代理类的收尾工作");
System.out.println();
return obj;
}
}
ProxyTest 测试类
package com.qianfeng.workone.example.dynamiciscglib;
import net.sf.cglib.proxy.Enhancer;
public class ProxyTest {
public static void main(String[] args) {
//设置一个增强器
Enhancer enhancer = new Enhancer();
//设置要生成代理的类的父类
enhancer.setSuperclass(Actor.class);
// 设置一个回调,每次通过代理对象来调用方法的时候,都会进入到对应拦截器中。
enhancer.setCallback(new ProxyFactory());
Actor actor = (Actor) enhancer.create();
actor.sing("演员");
actor.dance();
actor.price(10000);
}
}