这个是陈腐的热乎的,针对某个面试题写了的内容,如果有问题欢送来喷。
来看看他们的区别
动态/动静 | 区别 |
---|---|
动态 | 由程序员创立代理类或特定工具主动生成源代码再对其编译。在程序运行前代理类的.class文件就曾经存在了 |
动静 | 在程序运行时使用反射机制动态创建而成。 |
咱们先把动态代理和动静代理的代码放上来
看名字,这个是须要被代理的接口,无论是动态还是动静,都须要一个接口
ToBeProxyedInterface.java
public interface ToBeProxyedInterface { void addUser(String userId, String userName); void delUser(String userId); String findUser(String userId); void modifyUser(String userId, String userName);}
上面是两个类,ToBeProxyedService1.java,ToBeProxyedService2.java,动态代理只须要一个就能够了,动静代理为了试验其动态性,所以来了两个具体的Service,后边能够看Client的main办法实现,如何指定1还是2的service调用
ToBeProxyedService1.java
public class ToBeProxyedService1 implements ToBeProxyedInterface { @Override public void addUser(String userId, String userName) { System.out.println("ToBeProxyedService1.addUser"); } @Override public void delUser(String userId) { System.out.println("ToBeProxyedService1.delUser"); } @Override public String findUser(String userId) { System.out.println("ToBeProxyedService1.findUser"); return "张三"; } @Override public void modifyUser(String userId, String userName) { System.out.println("ToBeProxyedService1.modifyUser"); }}
ToBeProxyedService2.class
public class ToBeProxyedService2 implements ToBeProxyedInterface { @Override public void addUser(String userId, String userName) { System.out.println("ToBeProxyedService2.addUser"); } @Override public void delUser(String userId) { System.out.println("ToBeProxyedService2.delUser"); } @Override public String findUser(String userId) { System.out.println("ToBeProxyedService2.findUser"); return "张三2"; } @Override public void modifyUser(String userId, String userName) { System.out.println("ToBeProxyedService2.modifyUser"); }}
重点来类,动态代理,通过构造方法传入了具体的须要代理的Service,因而每一个Handler只能代理一个Service,再减少一个Service时候,就须要在对应一个Handler,扩大不太好
StaticProxyHandler.java
public class StaticProxyHandler implements ToBeProxyedInterface { // 指标对象 private ToBeProxyedService1 toBeProxyedService1; // 通过构造方法传入指标对象 public StaticProxyHandler(ToBeProxyedService1 toBeProxyedService1){ this.toBeProxyedService1=toBeProxyedService1; } @Override public void addUser(String userId, String userName) { try{ //增加打印日志的性能 //开始增加用户 System.out.println("start StaticProxyHandler-->addUser()"); toBeProxyedService1.addUser(userId, userName); //增加用户胜利 System.out.println("success StaticProxyHandler-->addUser()"); }catch(Exception e){ //增加用户失败 System.out.println("error StaticProxyHandler-->addUser()"); } } @Override public void delUser(String userId) { toBeProxyedService1.delUser(userId); } @Override public String findUser(String userId) { toBeProxyedService1.findUser(userId); return "张三"; } @Override public void modifyUser(String userId, String userName) { toBeProxyedService1.modifyUser(userId,userName); }}
最重点来了,动静代理,能够在外面看不到任何具体的Service是哪个,具体的指定哪个Service在后边的Client的main办法传入指定不同的Service。实际上动静代理是通过实现了InvocationHandler实现的
具体看下,newProxyInstance办法是通过入参传入指定的具体的哪个Service的动静绑定,而Handler中实现InvocationHandler中的invoke办法,才是真正调用的具体的办法的实现。
DynamicProxyHandler.java
public class DynamicProxyHandler implements InvocationHandler { // 指标对象 private Object targetObject; //绑定关系,也就是关联到哪个接口(与具体的实现类绑定)的哪些办法将被调用时,执行invoke办法。 public Object newProxyInstance(Object targetObject){ this.targetObject=targetObject; //该办法用于为指定类装载器、一组接口及调用处理器生成动静代理类实例 //第一个参数指定产生代理对象的类加载器,须要将其指定为和指标对象同一个类加载器 //第二个参数要实现和指标对象一样的接口,所以只须要拿到指标对象的实现接口 //第三个参数表明这些被拦挡的办法在被拦挡时须要执行哪个InvocationHandler的invoke办法 //依据传入的指标返回一个代理对象 return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(),this); } @Override //关联的这个实现类的办法被调用时将被执行 /*InvocationHandler接口的办法,proxy示意代理,method示意原对象被调用的办法,args示意办法的参数*/ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("start DynamicProxyHandler--invoke >>"); for(int i=0;i<args.length;i++){ System.out.println(args[i]); } Object ret=null; try{ /*原对象办法调用前解决日志信息*/ System.out.println("satrt DynamicProxyHandler call method -->>"); //调用指标办法 ret=method.invoke(targetObject, args); /*原对象办法调用后处理日志信息*/ System.out.println("success DynamicProxyHandler call method -->>"); }catch(Exception e){ e.printStackTrace(); System.out.println("error DynamicProxyHandler call method -->>"); throw e; } return ret; }}
上面的main办法能够看到,动态代理传入的就是具体的ToBeProxyedService1,无奈实现扩大
后边的动静代理我写了两遍,实际上每次传入的不同的ToBeProxyedService1和ToBeProxyedService2,别离都能够执行,不便动静扩大,后边如果再有ToBeProxyedService3,只有调用前批改就能够,不必批改具体的Handler,不便扩大了。
Client.java
public class Client { public static void main(String[] args){ //动态代理,每一个固定写死了具体的须要代理的类 StaticProxyHandler staticProxyHandler = new StaticProxyHandler(new ToBeProxyedService1()); staticProxyHandler.addUser("1111", "张三"); //动静代理,须要执行ToBeProxyedService1就传入ToBeProxyedService1,如果须要执行ToBeProxyedService2就传入ToBeProxyedService2 DynamicProxyHandler proxyHandler=new DynamicProxyHandler(); ToBeProxyedInterface service = (ToBeProxyedInterface) proxyHandler.newProxyInstance(new ToBeProxyedService1()); service.addUser("1111", "张三"); service = (ToBeProxyedInterface) proxyHandler.newProxyInstance(new ToBeProxyedService2()); service.addUser("1111", "张三"); }}