java 动态代理 黑马程序员学习笔记(8)
原创
©著作权归作者所有:来自51CTO博客作者灯塔kuaidao的原创作品,请联系作者获取转载授权,否则将追究法律责任
动态代理总结!!!
1. 动态代理解释:
2. JAVA的动态代理
代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理 消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对 象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
按照代理的创建时期,代理类可以分为两种。
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
动态代理:在程序运行时,运用反射机制动态创建而成。
3. 张孝祥老师讲动态代理中设计的一些扩展
OOP(Object oriented program):面向对象编程。Java中主要使用面向对象的思想来编程
AOP(Aspect oriented program):面向方面编程。为了弥补oop的不足,产生的面向方面(切面)的编程。
4. JVM生成的动态类必须实现一个或多个接口。如果没有实现接口,想要生成代理。那么就需要借助第三方的类库(CGLIB),使用CGLIB可以动态生成一个类的子类,用做该类的代理。
5.代理类的方法中除了要调用目标方法和对外返回结果外。不仅这样代理类的方法还可以在代理方法如下四个位置加上系统功能代码:
5.1.在调用目标方法之前
5.2.在调用目标方法之后
5.3.在调用目标方法前后
5.4.在处理目标方法异常的catch块中
Class proxy{
......①
void sayHello(){
......②
try{
target.sayHello();
}catch(Exception e){
......③
}
......④
}
}
StringBuffer与StringBuilder:他们都是可变的字符序列
StringBuilder:用在单线程中效率明显要高于StringBuffer,因为他不考虑线程安全地情况。
StringBuffer:用在多线程中有优势,考虑线程安全,怎么系统的稳定性。
Eg:以下是关于动态代理的小例子:
package cn.itcast.itcastweb.servelt;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
public class ProxyTest {
public static void main(String[] args) throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException {
//得到一个class
Class clazzProxy1=Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
System.out.println(clazzProxy1.getName());
System.out.println("begin constructor list");
//得到构造方法
Constructor[] constructors= clazzProxy1.getConstructors();
for( Constructor constructor:constructors){
//构造器的名字
String name=constructor.getName();
//拼串
StringBuilder sBuilder=new StringBuilder(name);
sBuilder.append('(');
Class[] clazzParams= constructor.getParameterTypes();
for(Class clazzParam:clazzParams){
sBuilder.append(clazzParam.getName()).append(',');
}
//去掉最后一个,
if( clazzParams!=null &&clazzParams.length!=0)
sBuilder.deleteCharAt(sBuilder.length()-1);
sBuilder.append(')');
System.out.println(sBuilder.toString());
}
System.out.println("begin methods list");
//得到构造方法
Method[] methods= clazzProxy1.getMethods();
for( Method method:methods){
//构造器的名字
String name=method.getName();
//拼串
StringBuilder sBuilder=new StringBuilder(name);
sBuilder.append('(');
Class[] clazzParams= method.getParameterTypes();
for(Class clazzParam:clazzParams){
sBuilder.append(clazzParam.getName()).append(',');
}
//去掉最后一个,
if( clazzParams!=null &&clazzParams.length!=0)
sBuilder.deleteCharAt(sBuilder.length()-1);
sBuilder.append(')');
System.out.println(sBuilder.toString());
}
//单线程sbuilder高翔
//多线程sbuffer高效;考虑线程的安全
/*
* 创建实例对象
*/
System.out.println("begin methods list");
Constructor constructor =clazzProxy1.getConstructor(InvocationHandler.class);
//invocatiionHander1
class MyInvocationHander1 implements InvocationHandler{
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return null;
}
}
Collection proxy1=(Collection) constructor.newInstance(new MyInvocationHander1());
//null 是谁返回的,(toString 返回的null)
System.out.println(proxy1+":procy1");
//proxy1.clear();
//proxy1.size(); //会返回null(带返回值!!!!!!)、
//使用匿名内部类方式调用
Collection proxy2=(Collection) constructor.newInstance(new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return null;
}
});
//指定目标
final ArrayList target =new ArrayList();
//方法三
Collection proxy3 = (Collection) getProxy(target,new Advicer() {
@Override
public void beforeMethod(Method method) {
}
@Override
public void afterMethod(Method method) {
}
});
proxy3.add("xxx");
proxy3.add("x22x");
proxy3.add("xtttx");
System.out.println(proxy3.size());
//调用add会找invoke方法,相互之间不关联
}
//目标抽取
private static Object getProxy(final Object target,final Advice advice) {
System.out.println("zhixing");
Object proxy3=Proxy.newProxyInstance(
//Collection.class.getClassLoader(),
target.getClass().getClassLoader(),
//new Class[]{Collection.class},
target.getClass().getInterfaces(),
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
/*long beginTime=System.currentTimeMillis();
Object retVal=method.invoke(target, args);
long endTime=System.currentTimeMillis();
System.out.println(method.getName()+"run time of"+(endTime-beginTime));
return retVal;*/
new Advicer().beforeMethod(method);
Object retVal=method.invoke(target, args);
new Advicer().afterMethod(method);
return retVal;
}
});
return proxy3;
}
}
//invocation 内部的原理
//构造方法接受一个invocationHandler对象,接受对象要使用,内部代码会怎样呢?
//调用add方法invocation就执行一次
//代理对象的三个要素,
/*
* method.invoke(target,args)
* 代理对象,方法,参数
*
*
*
*
*/
Advice.java
package cn.itcast.itcastweb.servelt;
import java.lang.reflect.Method;
public interface Advice {
//q
void beforeMethod(Method method);
//h
void afterMethod(Method method);
}
Advicer.java
package cn.itcast.itcastweb.servelt;
import java.lang.reflect.Method;
public interface Advice {
//前
void beforeMethod(Method method);
//后
void afterMethod(Method method);
}