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);
}
}