Spring中的Aop(一)--使用Proxy.newProxyInstance和cglib创建代理对象
一、什么是Aop
Aop是面向切面编程的简称,是通过预编译和运行期间动态代理实现程序功能的一共技术方式。
下面我们举一个实际的例子来进行说明。
例子:手机生产厂家只生产手机,手机代理帮助厂家卖手机,并收取20%的费用,示例图如下:
下面我们编写一个类表示厂家,一个代理类表示代理商,来实现该功能。
二、使用Proxy.newProxyInstance
方法对实现接口的类进行动态代理
使用Proxy创建代理类,被代理的类必须要实现接口,下面我们开始编写代码实现这个过程;
2.1 定义生产厂商
定义接口
package org.study.proxy;
public interface IProducer {
/**
* 销售产品,并拿到钱
* @param amount
*/
void saleProduct(float amount);
/**
* 提供售后服务
* @param amount
*/
void afterService(float amount);
}
实现接口
package org.study.proxy.impl;
import org.study.proxy.IProducer;
public class ProducerImpl implements IProducer {
@Override
public void saleProduct(float amount) {
System.out.println("saleProduct money:" + amount);
}
@Override
public void afterService(float amount) {
System.out.println("afterService money:" + amount);
}
}
我们的生产厂家类已经编写完成;
2.2 编写代理商,代理商对saleProduct方法进行增强
package org.study.proxy;
import org.study.proxy.impl.ProducerImpl;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) {
IProducer producer =new ProducerImpl();
/**
* ClassLoader loader 类加载器,用于加载代理对象的字节码
* Class<?>[] interfaces 字节码数组,用于让代理对象和被代理对象有相同的方法
* InvocationHandler h 处理方法,用于方法增强
*/
IProducer proxyProducer = (IProducer) Proxy.newProxyInstance(
producer.getClass().getClassLoader(),
producer.getClass().getInterfaces(),
/**
* Object proxy 被代理的类
* Method method 被代理类的方法
* Object[] args 方法参数
*/
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("saleProduct")) {
float amount = (float) args[0];
return method.invoke(producer, amount * (float) 0.8);
} else {
return method.invoke(producer, args);
}
}
});
proxyProducer.saleProduct(1000f);
proxyProducer.afterService(1000f);
}
}
主要的技术点:
使用Proxy.newProxyInstance方法,对类进行增强,并返回了和代理类同样的对象和方法;
2.3 运行结果
通过运行结果,可以看到,代理类帮我们卖出去了产品,厂商拿到了80%的钱,目标实现;
三、使用cglib对不实现接口的类进行动态代理
1、代码编写
cglib是一个类库,它可以在运行期扩展Java类与实现Java接口;cglib中使用Enhancer
类来进行代理,代码如下:
package org.study.cglib;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class Client {
public static void main(String[] args) {
Producer producer = new Producer();
Producer enhancerProducer = (Producer) Enhancer.create(producer.getClass(), new MethodInterceptor() {
/**
* @param proxy 被代理对象
* @param method 代理的方法
* @param args 方法参数
* @param methodProxy 当前执行方法的代理对象
* @return
* @throws Throwable
*/
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
if (method.getName().equals("saleProduct")) {
float amount = (float) args[0];
return method.invoke(producer, amount * (float) 0.8);
} else {
return method.invoke(producer, args);
}
}
});
enhancerProducer.saleProduct(1000f);
enhancerProducer.afterService(1000f);
}
}
2、运行结果
方法依然如预期执行了。
四、总结
1、使用cglib类库,来对类进行代理和Proxy的用法基本相同,都返回一个增强后的类,该类和原来的类,拥有相同的方法,并增加了某些方法的功能;
2、Aop的基本原理就是对类进行增强,在代理类中抽象出公共方法。