***模式(Proxy):静态***(Static Proxy)、动态***(Dynamic Proxy)和CGLIB***
一、***模式
为其他对象提供一种***以控制对这个对象的访问。
二、***模式结构图
三、静态***
这种***方式需要***对象和目标对象实现一样的接口。
1、优点: 可以在不修改目标对象的前提下扩展目标对象的功能。
2、缺点: 冗余:由于***对象要实现与目标对象一致的接口,会产生过多的***类。不易维:一旦接口增加方法,目标对象与***对象都要进行修改。
3、代码实现:
//被追女孩子类
public class Girl {
private String name;
public Girl(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/* *小时候看到喜欢的女孩子,就会给写情书,但是人怂又不敢亲自去送,因此只好请求别人***我去送。 *上述事实是一个***模式的简单应用,一起来来看看如何让别人来***你去送情书 *公共接口 */
public interface LoveLetter {
public void sendLoveLetter(String name);
}
/* * 追求者类 * */
public class Suitor implements LoveLetter {
@Override
public void sendLoveLetter(String name) {
System.out.println("哈喽,"+name+"这是亚峰给你的情书!");
}
}
/* * 追求者***类 * */
public class SuitorProxy implements LoveLetter {
private LoveLetter suitor;
@Override
public void sendLoveLetter(String name) {
if(suitor == null){
suitor = new Suitor();
}
suitor.sendLoveLetter(name);
}
}
public class SuitorTest {
public static void main(String[] args) {
Girl girl = new Girl("晓双");
//在这里送情书的实际上是追求者,而不是追求者***
SuitorProxy proxy = new SuitorProxy();
proxy.sendLoveLetter(girl.getName());
}
}
静态***中从客户端的角度来看,客户端是不知道实际的追求者的,但是情书还是来自于追求者,而不是其***。
四、动态***
动态***利用了JDK API,动态地在内存中构建***对象,从而实现对目标对象的***功能。动态***又被称为JDK***或接口***。
1、静态***与动态***的区别主要在:
(1)静态***在编译时就已经实现,编译完成后***类是一个实际的class文件
(2)动态***是在运行时动态生成的,即编译完成后没有实际的class文件,而是在运行时动态生成类字节码,并加载到JVM中。
2、代码实现
//被追女孩子和上述类同
/* *小时候看到喜欢的女孩子,就会给写情书,但是人怂又不敢亲自去送,因此只好请求别人***我去送。 *上述事实是一个***模式的简单应用,一起来来看看如何让别人来***你去送情书 *公共接口,仅仅是去掉了方法参数 */
public interface LoveLetter {
public void sendLoveLetter();
}
/* * 追求者类 * */
public class Suitor implements LoveLetter {
private Girl girl;
public Suitor(Girl girl) {
this.girl = girl;
}
@Override
public void sendLoveLetter() {
System.out.println("哈喽,"+girl.getName()+"这是亚峰给你的情书!");
}
}
//事件处理器,必须实现InvocationHandeler接口
public class InvocationHandlerImp implements InvocationHandler {
//target即为需要被***的对象
private Object target;
public InvocationHandlerImp(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开始送情书");
Object object = method.invoke(target);
System.out.println("情书送出去了");
return object;
}
}
测试类
public class SuitorTest {
public static void main(String[] args) {
Girl girl = new Girl("晓双");
Suitor suitor = new Suitor(girl);
InvocationHandlerImp invocationHandlerImp = new InvocationHandlerImp(suitor);
LoveLetter loveLetter = (LoveLetter) Proxy.newProxyInstance(LoveLetter.class.getClassLoader(),new Class[]{LoveLetter.class},invocationHandlerImp);
loveLetter.sendLoveLetter();
}
}
结果:
开始送情书
哈喽,晓双这是亚峰给你的情书!
情书送出去了
五、CGLIB***
cglib is a powerful, high performance and quality Code Generation Library. It can extend JAVA classes and implement interfaces at runtime.
cglib (Code Generation Library )是一个第三方代码生成类库,运行时在内存中动态生成一个子类对象从而实现对目标对象功能的扩展。
1、cglib特点
(1)JDK的动态***有一个限制,就是使用动态***的对象必须实现一个或多个接口。
(2)如果想***没有实现接口的类,就可以使用CGLIB实现。
(3)CGLIB是一个强大的高性能的代码生成包,它可以在运行期扩展Java类与实现Java接口。它广泛的被许多AOP的框架使用,例如Spring AOP和dynaop,为他们提供方法的interception(拦截)。
(4)CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它需要你对JVM内部结构包括class文件的格式和指令集都很熟悉。
2、cglib与动态***最大的区别就是
(1)使用动态***的对象必须实现一个或多个接口
(2)使用cglib***的对象则无需实现接口,达到***类无侵入。