代理模式概念
代理就是帮别人做事情,如:工厂的中介,中介负责为工厂招收工人,那么中介就是工厂的代理;客户通过商家购买东西,商家向厂家购买货物,商家就是工厂的代理
在开发中存在a类需要调用c类的方法,完成某一个功能,但是c禁止a调用。这时,可以在a和c之间创建一个b类代理,a类访问b类,b类访问c类。例如:登录的时候需要进行短信验证,这个时候代理就是中国移动的子公司来完成短信的发送功能
代理模式就是为其他对象提供一种代理来控制这个对象的访问,在某些情况下一个对象不适合或不能直接引用另一个对象,而代理对象可以在客户类和目标对象直接起到中介的作用
功能增强:其中目标对象实现真正的功能,但是代理对象可以对目标对象的功能做进一步的扩充,例如打官司的时候,原告陈述事实,律师则在这基础上进行修饰以及法律条文的引用
代理的规则:被代理类和代理类都必须实现同一个接口的方法
静态代理
张三(被代理的对象)犯法了,但是在法庭上不能为自己辩护,这时候律师(代理类的对象)就起到了代理的作用,当法官问(调用)张三(被代理的对象)的时候,需要通过律师来陈述。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
public class Test{ public static void main(String[] args) { specker specker = new Lawyer(); specker.speck(); } }
interface specker{ public void speck(); }
class ZhangSan implements specker{ @Override public void speck() { System.out.println("我要赚钱!"); } }
class Lawyer implements specker{ @Override public void speck() { ZhangSan zhangsan = new ZhangSan(); System.out.println("根据刑法,你赚钱方法有问题!"); zhangsan.speck(); System.out.println("你要坐牢!"); } }
|
- 定义了
specker
接口和speck()
方法,ZhangSan类和Lawyer类都继承并实现
- Lawyer调用方法时在ZhangSan的基础上进行补充增强
调用截图:
动态代理
动态代理是利用的反射机制动态地生成代理的对象,我们不需要知道谁代理谁。代理类的那部分代码被固定下来了,不会因为业务的增加而逐渐庞大。
JDK代理
JDK动态代理规则:
- 实现代理的类必须实现
InvocationHandler
接口
- 在代理类的invoke编写调用的方法
- 通过
Proxy.newProxyInstance(classloader,interface、invocationhandler)
创建代理类并实现实际类型的转换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
public class Test{ public static void main(String[] args) {
LawyerProxy lawyerProxy = new LawyerProxy(new ZhangSan()); specker specker = (specker) Proxy.newProxyInstance(Test.class.getClassLoader(),new Class[]{specker.class},lawyerProxy); specker.speck(); LawyerProxy lawyerProxy1 = new LawyerProxy(new Lisi()); specker specker1 = (specker) Proxy.newProxyInstance(Test.class.getClassLoader(),new Class[]{specker.class},lawyerProxy); specker1.speck(); } }
interface specker{ public void speck(); }
class Lisi implements specker{ @Override public void speck() { System.out.println("别问我,我什么都不知道!"); } }
class ZhangSan implements specker{ @Override public void speck() { System.out.println("我要赚钱!"); } }
class LawyerProxy implements InvocationHandler{
Object object; public LawyerProxy(Object object){ this.object=object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().equals("speck")){ System.out.println("根据刑法,你赚钱方法有问题!"); method.invoke(this.object,args); System.out.println("你要坐牢!"); } return null; } }
|
通过CGLIB实现动态代理
有些类有同样的方法名,但是没有实现接口,一般是引入的jar包,这时就可以使用CGLIB的动态代理
原理是继承,通过继承目标类创建它的子类,在子类中重写父类中的方法,实现功能的修改
- 需要导入jar包:cglib.jar,核心包和依赖包(spring_core.jar已经集成了这两个包,因此,导入此包即可)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
public class Test{ public static void main(String[] args) { LawyerIntercepter lawyerIntercepter = new LawyerIntercepter(new Lisi()); Lisi lisi = (Lisi) Enhancer.create(Lisi.class,lawyerIntercepter); lisi.speck(); } }
class Lisi{ public void speck() { System.out.println("别问我,我什么都不知道!"); } }
class LawyerIntercepter implements MethodInterceptor{ private Object object; LawyerIntercepter(Object object){ this.object=object; } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { if (method.getName().equals("speck")){ System.out.println("这是java的cglib动态代理"); method.invoke(object,objects); System.out.println("你有罪!"); } return null; } }
|