代理1

1.静态代理

静态代理,实际上就是我们自个写好,定死一些类,然后这些类按照继承和实现接口的方式来实现一些aop的功能。当然,这些模式适用于固定的流程,比如事先定好的aop规则就是:让类A的Aop=>处理日志,让类B的Aop=>处理数据库,最后到业务逻辑。如果我们想要在这个链条后面增加aop,我们直接重新一个类C的Aop,然后接入类B的Aop。这样就可以了,但是这样的话,是非常固定的,你没办法去改变原来的aop顺序,如果我们想让类A和类B的aop顺序交换,那就没办法了。

针对各种aop的顺序,可以有很多种组合,这样子算下来,如果要覆盖所有的组合,要写很多类,不管是实现接口【聚合】,还是继承,都会带来类爆炸的结果。

而且,如果是直接采用手写的方式,aop的业务是写死的,没办法动态获取,这种写死的效果如果是内部开发,几个人协商好就一起用这个aop那还好,如果是一个框架提供的,那么肯定就是要动态获取到相应的aop逻辑了,所以也不能直接写死aop的类了,也就是说,基本上,静态代理用不了了。

这里把要被aop的对象成为目标,把完成增强的对象成为代理类

 

    1-1.聚合代理

        所谓的聚合,实际上就是,把目标对象聚合到代理类中。

如果是想要多个增强,比如增强了log之后,还想要增强数据库。那么就得使用类似如下的方法:

像俄罗斯套娃一样,不断套进去。诚然,聚合方式产生的类会比较少,但是,每个aop类还是都要定义出来,也会有类爆炸。

 

 

     1-2.继承代理

      继承就是可以拿到目标对象的所有方法。

     现在有2个aop,那么组合的方法有就是AB和BA,那么就有两种组合方法,所以类爆炸是必然的。

 

2.动态代理

作业:给定一个接口和一个对应的实现类,给定一个代理工具,能够根据对应的实现类,生成我们类似下图的一个代理类。

注意:实现类里面的所有方法都要实现增强,不支持返回值,支持参数传递。

 


package com.luban.proxy;

import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

public class MySelfProxyUtil {
    /**1.定义package 固定为 => package com.luban.dao;
     * 1.拿到目标对象的接口
     * 2.实现对应额接口
     * 3.定义变量,把target给变量
     * 4.拿到接口里面的所有方法
     * 5.遍历每个方法,拿到每个方法里面参数列表,组合好之后,传入方法里面
     * 6.方法里面调用变量的同名方法,传入参数
     * 7.定义构造方法
     package com.luban.dao;
     import com.luban.dao.动态代理.LubanDao;
     public class Result implements LubanDao {
         private LubanDao lubanDao;
         public Result(LubanDao lubanDao) {
            this.lubanDao = lubanDao;
        }

        public void query() {
            System.out.println("1111");
            lubanDao.query();
        }

        public void quert(String str) {
            System.out.println("1111");
            lubanDao.quert(str);
        }
     }
     */
    public static Object newInstance(Object target){
        Object proxy = null;
        Class inter = target.getClass().getInterfaces()[0];
        String InterName = inter.getSimpleName();
        Method[] methods = inter.getMethods();

        String line = "\n";
        String tab = "\t";
        String packageName = "package com.cjf.proxy;"+line;
        String importClass = "import "+inter.getName()+";"+line;
        String clazzFirstLineContent = " public class $proxy implements "+InterName+"{"+line;
        String filedContent = tab+"private "+InterName+" target;"+line;
        String ConsturctContent = tab+"public $proxy("+InterName+" target){"+line;
        String ConsturctContentTwo = tab+tab+"this.target=target;"+line;
        String ConsturctContentThree = tab+"}"+line;
        String ConsturctContentResult = ConsturctContent+ConsturctContentTwo+ConsturctContentThree;
        String method = "";
        String result = "";
        if(methods!=null&&methods.length>0){
            for(Method OneMethod:methods){
                String MethodName = OneMethod.getName();
                String ReturnName = OneMethod.getReturnType().getSimpleName();
                Class[] Parameters = OneMethod.getParameterTypes();
                String ParameterStr = "";//拼接方法的参数
                String ParameterInner = "";// 传递给内部函数的参数
                int flag = 0;
                for(Class OneParameter:Parameters){
                    ParameterStr+=OneParameter.getSimpleName()+" p"+flag+",";
                    ParameterInner+=" p"+flag+",";
                    flag++;
                }
                if (Parameters.length>0){
                    ParameterStr=ParameterStr.substring(0,ParameterStr.lastIndexOf(",")-1);
                    ParameterInner=ParameterInner.substring(0,ParameterInner.lastIndexOf(",")-1);
                }

                String OneMethodStr = tab+"public "+ReturnName+" "+MethodName+"("+
                                      ParameterStr+"){"+line;
                String OneMethodStrBody = tab+tab+"System.out.println(\"1111\");"+line;
                String OneMethodStrBody2 = "";
                if(!"void".equals(ReturnName)){
                    OneMethodStrBody2 = tab+tab+"return ";
                }
                OneMethodStrBody2 += "target."+MethodName+"("+ParameterInner+");"+line;
                String OneMethodStrBody3 = "}"+line;
                method+=OneMethodStr+OneMethodStrBody+OneMethodStrBody2+OneMethodStrBody3;
            }
        }
        result = packageName+importClass+clazzFirstLineContent+filedContent+ConsturctContentResult+method+"}"+line;
        File file = new File("D:\\com\\cjf\\proxy\\$proxy.java");
        try{
            if(!file.exists()){
                file.createNewFile();
            }else{
                file.delete();
                file.createNewFile();
            }

            FileWriter fw = new FileWriter(file);
            fw.write(result);
            fw.flush();
            fw.close();

            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

            StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);
            Iterable units = fileMgr.getJavaFileObjects(file);

            JavaCompiler.CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);
            t.call();
            fileMgr.close();

            URL[] urls = new URL[]{new URL("file:D:\\\\")};
            URLClassLoader urlClassLoader = new URLClassLoader(urls);
            Class clazz = urlClassLoader.loadClass("com.cjf.proxy.$proxy");

            Constructor constructor = clazz.getConstructor(inter);

            proxy = constructor.newInstance(target);
        }catch (Exception e){
            e.printStackTrace();
        }
        return proxy;
    }
}

 

 

 

package com.luban.dao.动态代理;

public class LubanDaoImpl implements LubanDao{

    public void query(){
        System.out.println("query");

    }

    public void quert(String str) {
        System.out.println(str);
    }
}

 

最终生成的类如下:

package com.cjf.proxy;
import com.luban.dao.动态代理.LubanDao;
 public class $proxy implements LubanDao{
	private LubanDao target;
	public $proxy(LubanDao target){
		this.target=target;
	}
	public void query(){
		System.out.println("1111");
target.query();
}
	public String quert(String p){
		System.out.println("1111");
		return target.quert( p);
}
}

 

 

 

 

 

 

 

      

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值