一、代理模式的目的
1.保护目标对象
2.增强目标对象
二、代理模式类型
静态代理、动态代理
三、静态代理
其中一种实现逻辑:通过持有被代理对象的引用,在被代理对象执行之前或者之后添加新的处理逻辑,达到增强被代理对象的效果。
package com.ns.proxy.staticproxy.demo1;
/**
* 顶层接口(Person)
*/
public interface Person {
void findLove();
}
package com.ns.proxy.staticproxy.demo1;
/**
* 被代理对象(目标对象)
*/
public class Son implements Person {
@Override
public void findLove() {
System.out.println("儿子也觉得不小了,该给自己找个对象了");
}
}
package com.ns.proxy.staticproxy.demo1;
/**
* 代理类(父亲,帮儿子找对象的)
* 通过持有Son的引用实现对Son的代理
*/
public class Father implements Person{
private Son son;
public Father(Son son){
this.son = son;
}
@Override
public void findLove() {
System.out.println("爸爸先给儿子物色个肤白貌美的对象");
son.findLove();
System.out.println("儿子同意了,可以开始交往了");
}
}
package com.ns.proxy.dynamicproxy.jdkproxy;
/**
* 测试类
*/
public class TestJdkProxy {
public static void main(String[] args) {
Person person = (Person) new MeiPoJDKProxy().getInstance(new Customer());
person.findLove();
}
}
四、动态代理
动态代理分为两种:
JDK动态代理、Cglib动态代理
主要区别:
1.JDK动态代理是实现了被代理对象的接口,Cglib是继承了被代理对象(具体实现逻辑)
2.JDK和Cglib都是在运行期生成字节码,JDK是直接写class字节码,Cglib使用ASM框架写class字节码,Cglib代理更负责,生成代理类比JDK效率低
3.JDK调用代理类方法,是通过反射机制调用,Cglib是通过FastClass机制直接调用方法,执行效率高
JDK动态代理
(1) 原理:
通过实现InvocationHandler(字节码重组)
1.拿到被代理对象的引用,并且获取到它所有的接口,反射获取
2.JDK Proxy类重新生成一个新的类,同时新的类要实现被代理所实现的所有接口
3.动态生成Java代码,把新加的业务逻辑方法由一定的代码逻辑去调用
4.编译新生成的Java代码.class
5.重新加载到JVM并运行
(2)Demo
package com.ns.proxy.dynamicproxy.jdkproxy;
/**
* 顶层接口类
*/
public interface Person {
void findLove();
}
package com.ns.proxy.dynamicproxy.jdkproxy;
/**
* 被代理对象
*/
public class Customer implements Person {
@Override
public void findLove() {
System.out.println("想找个对象");
}
}
package com.ns.proxy.dynamicproxy.jdkproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 代理类
*/
public class MeiPoJDKProxy implements InvocationHandler {
private Object target;
public Object getInstance(Object target){
this.target = target;
Class<?> clazz = target.getClass();
return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object obj = method.invoke(this.target,args);
after();
return obj;
}
private void before() {
System.out.println("我是媒婆,我要给你物色对象,已经拿到你的需求");
System.out.println("开始物色对象");
}
private void after() {
System.out.println("你俩觉得合适的话,就办事吧");
}
}
package com.ns.proxy.dynamicproxy.jdkproxy;
/**
* 测试类
*/
public class TestJdkProxy {
public static void main(String[] args) {
Person person = (Person) new MeiPoJDKProxy().getInstance(new Customer());
person.findLove();
}
}
Cglib动态代理
通过实现MethodInterceptor,重写intercept方法实现动态代理
package com.ns.proxy.dynamicproxy.cglibproxy;
/**
* Person类,策略的通用接口
*/
public interface Person {
void findLove();
}
package com.ns.proxy.dynamicproxy.cglibproxy;
/**
* 客户类,被代理类(实现Person类的目的是为了实现简单的策略)
*/
public class Customer implements Person{
public void findLove(){
System.out.println("肤白貌美大长腿");
}
}
package com.ns.proxy.dynamicproxy.cglibproxy;
/**
* 妹子类,被代理类(实现Person类的目的是为了实现简单的策略)
*/
public class MeiZi implements Person{
@Override
public void findLove() {
System.out.println("高富帅");
}
}
package com.ns.proxy.dynamicproxy.cglibproxy;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* 代理类
*/
public class CglibMeiPoProxy implements MethodInterceptor {
public Object getInstance(Class<?> clazz){
Enhancer enhancer = new Enhancer();
//要把哪个设置成即将生成的新类父类
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
before();
Object obj = methodProxy.invokeSuper(o,objects);
after();
return obj;
}
private void after() {
System.out.println("如何合适的话,准备完事");
}
private void before() {
System.out.println("我是媒婆,我要开始给你物色对象了,已经拿到你的需求");
System.out.println("开始物色");
}
}
package com.ns.proxy.dynamicproxy.cglibproxy;
/**
* 测试类
*/
public class CglibTest {
public static void main(String[] args) {
CglibMeiPoProxy cglibMeipoProxy = new CglibMeiPoProxy();
//策略模式,传入的类不同,走不同的具体实现
// Person person = (Person)cglibMeipoProxy.getInstance(MeiZi.class);
Person person = (Person)cglibMeipoProxy.getInstance(Customer.class);
person.findLove();
}
}
五、总结
静态代理与动态代理的区别
1.静态代理只能通过手动完成代理操作,如果被代理类增加新的方法,代理类需要同步新增,违背开闭原则
2.动态代理采用运行时动态生成代码的方式,取消了被代理类的扩展限制,符合开闭原则
3.若代理模式要对目标类的增强逻辑扩展,结合策略模式,只需要新增策略类即可完成,无需修改代理类的代码
代理模式的优点
1.代理模式能将代理对象与真实的被调用的目标对象分离
2.一定程度上降低了系统的耦合度,扩展性好
3.可以起到保护目标对象的作用
4.可以对目标对象的功能增强
代理模式的缺点
1.代理模式会造成系统设计中类的数量增加
2.在客户端和目标对象增加一个代理对象,会造成请求速度变慢
3.增加了系统的复杂度
Spring中的代理选择原则
当Bean有实现接口时,Spring就会用jdk的动态代理
当Bean没有实现接口时,Spring就用Cglib
注:该文章内容均为学习过程中的记录,若有与其他大哥的文章雷同,请谅解
希望各位都可以学以致用
3065

被折叠的 条评论
为什么被折叠?



