除了装饰者模式,动态代理也可用于进行方法增强,并且不用编写相关类,在不修改源码的情况下起到增强方法的作用。
1.基于接口的动态代理
此方法使用 jdk 自带的 api Proxy类的newProxyInstance方法实现,此方法的代理对象要求至少是实现一个接口,具体例子如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| public class Producer implements IProducer{ @Override public void sale(float money) { System.out.println("销售产品,并拿到钱:"+money); }
@Override public void afterSale(float money) { System.out.println("提供售后服务,并拿到钱:"+money); } }
public class Client {
public static void main(String[] args) { Producer producer = new Producer();
IProducer proxyInstance = (IProducer) Proxy.newProxyInstance(producer.getClass().getClassLoader(), producer.getClass().getInterfaces(), new InvocationHandler() {
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { float money = (float) args[0]; if (method.getName().equals("sale")) { money *= 0.8f; } return method.invoke(producer, money); } }); proxyInstance.sale(10000f);
} }
|
2.基于子类的动态代理
如果被代理对象没有实现接口,就要使用基于子类的动态代理,要求被代理对象不能是最终类,使用Enhancer类的create方法,利用了cglib,使用maven的项目需导入坐标
1 2 3 4 5
| <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.1_3</version> </dependency>
|
具体例子如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| public class Producer{
public void sale(float money) { System.out.println("销售产品,并拿到钱:"+money); }
public void afterSale(float money) { System.out.println("提供售后服务,并拿到钱:"+money); } }
public class Client { public static void main(String[] args) { final Producer producer = new Producer();
Producer proxyProducer = (Producer) Enhancer.create(producer.getClass(), new MethodInterceptor() {
@Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { float money = (float) args[0]; if (method.getName().equals("sale")) { money *= 0.8f; } return method.invoke(producer, money); } }); proxyProducer.sale(10000f); } }
|
使用过动态代理之后可以对Producer的sale方法进行增强,将收到钱数额变成原来的0.8倍。