手动写源码---模拟实现动态代理
AOP的实现有两种,一种是接口的实现,一种是产生自己实现,分别的代表为JDK的Proxy和CGLIB的Proxy
下面是模拟接口代理实现 ,通过模拟JDK的动态代理,更深刻的理解
通过动态代理可以面向切面编程
1 定义被代理的对象和接口
- public interface BookInterface {
- void selling();
- }
- public interface PhoneInterface {
- void selling();
- }
- public class Book implements BookInterface {
- @Override
- public void selling() {
- System.out.println("books selling.....");
- }
- }
- public class VivoPhone implements PhoneInterface {
- @Override
- public void selling() {
- System.out.println("selling vivo x5");
- }
- }
2 定义切面类
- public class TimeAspect {
- static long bgn;
- public static void before(){
- bgn = System.currentTimeMillis();
- System.out.println("begin time... " + bgn);
- }
- public static void after(){
- long end = System.currentTimeMillis();
- System.out.println("end time... " + (end-bgn));
- }
- }
- public class LogAspect{
- public static void before(){
- System.out.println("begin log...");
- }
- public static void after(){
- System.out.println("finish log...");
- }
- }
3 定义InvocationHander 代理接口
- import java.lang.reflect.Method;
- public interface InvocationHander {
- public void invoke(Object o,Method m);
- }
代理类(切面编程里面也可以做一些特殊的处理)
- import java.lang.reflect.Method;
- import jdkproxy.LogTranService;
- import jdkproxy.TimeTranService;
- public class ProxyHander implements InvocationHander {
- private Object target;
- public ProxyHander(Object target) {
- this.target = target;
- }
- @Override
- public void invoke(Object o, Method m) {
- try {
- TimeTranService.before();
- if(!(o instanceof BookInterface)){//只有非BookInterface接口调用日志
- LogTranService.before();
- }
- m.invoke(target);
- if(!(o instanceof BookInterface)){
- LogTranService.after();
- }
- TimeTranService.after();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
动态代理类
- import java.io.File;
- import java.io.IOException;
- import java.lang.reflect.Constructor;
- import java.lang.reflect.Method;
- import javax.tools.JavaCompiler;
- import javax.tools.JavaCompiler.CompilationTask;
- import javax.tools.StandardJavaFileManager;
- import javax.tools.ToolProvider;
- import org.apache.commons.io.FileUtils;
- public class Proxy {
- /*
- * 空的构造函数
- */
- private Proxy(){
- }
- /*
- * 返回代理类
- */
- public static Object newProxyInstance(Class inter,InvocationHander h){
- String packageName = inter.getPackage().getName();
- // String temp = new String(packageName);
- String proxyClassName = "$"+packageName.replace(".","_") + "_" + inter.getSimpleName() +"Proxy";
- String InHanderPackage = h.getClass().getPackage().getName();
- String rt = "\r\n";// 换行
- String methodCode = "";
- for (Method method:inter.getMethods()) {
- methodCode+=" @Override"+rt+
- " public void "+ method.getName()+"() {"+rt+
- " try{"+rt+
- " Method method = "+inter.getName()+".class.getMethod(\""
- + method.getName()+ "\");"+rt+
- " h.invoke(this,method); "+rt+
- " }catch(Exception e ){" +rt+
- " e.printStackTrace();" +rt+
- " }"+rt+
- " }";
- }
- /*
- * 总的java代码
- */
- String javaCode=
- "package "+packageName+";"+rt+
- "import "+InHanderPackage+".InvocationHander;"+rt+
- "import java.lang.reflect.Method;"+rt+
- "public class "+proxyClassName+" implements "+inter.getName()+" {"+rt+
- " public "+proxyClassName+"("+InHanderPackage+".InvocationHander h) {"+rt+
- " super();"+rt+
- " this.h = h;"+rt+
- " }"+rt+
- " private "+InHanderPackage+".InvocationHander h;"+rt+
- methodCode+rt+
- "}";
- /*
- * 生成java文件
- */
- // 生成文件路径
- String filename = System.getProperty("user.dir")+"/bin/"+packageName.replace(".", "//")+"/"+proxyClassName+".java";
- File file = new File(filename);
- try {
- // 需要commons-io的jar方便的操作文件
- FileUtils.writeStringToFile(file, javaCode);
- } catch (IOException e) {
- e.printStackTrace();
- }
- // 编译 拿到编译器
- JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
- // 文件管理
- StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);
- //获取文件
- Iterable units = fileMgr.getJavaFileObjects(filename);
- // 编译任务
- CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);
- // call进行编译
- t.call();
- try {
- fileMgr.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- // load到内存
- ClassLoader cl = ClassLoader.getSystemClassLoader();
- try {
- Class c = cl.loadClass(packageName+"."+proxyClassName);
- Constructor ctr = c.getConstructor(InvocationHander.class);
- return ctr.newInstance(h);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- }
4 测试
- import org.junit.After;
- import org.junit.Before;
- import org.junit.Test;
- public class TestProxy {
- @Before
- public void before(){
- System.out.println("-----------------start-------------------");
- }
- @Test
- public void test() {
- Book book = new Book();
- InvocationHander h = new ProxyHander(book);
- BookInterface bi = (BookInterface)Proxy.newProxyInstance(BookInterface.class,h);
- bi.selling(); // 没有日志打印
- System.out.println("==================分割==============================");
- PhoneInterface car = new VivoPhone();
- h = new ProxyHander(car);
- PhoneInterface pi = (PhoneInterface)Proxy.newProxyInstance(PhoneInterface.class,h);
- pi.selling(); // 有日志打印
- }
- @After
- public void after(){
- System.out.println("-----------------end-------------------");
- }
- }
Proxy类里面生成代理类名称的方法是根据包名来的,全类名长度加起来超过250多个长度可能会让java类无法编译,那就需要特殊处理了。超过250个长度的全类名那种项目没见过,不考虑
上面是他的原理,spring中如何使用aop呢?
请参考