黑马程序员——高新技术(三)

来源:互联网 发布:图片横向滚动js代码 编辑:程序博客网 时间:2024/05/20 13:06

----------------------    android培训    java培训   期待与您交流!    ----------------------

1,代理

为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能。
采用工厂模式和配置文件方式进行管理,不需要改客户端程序,比如你要给你的项目测试运行时间,在方法前后计算时间,这时改配置文件用的是代理,
最后觉得性能可以,可以卖给用户了,这时候要把计算时间的代码去掉,修改配置文件就可以了。
实现同样的接口,没接口CGLIB库可以生成一个类的子类(一个类的子类也可以用作该类的代理),用接口引用指向子类对象,代理类要调用目标类。
代理类可以进行测试,也可以和目标类通过配置文件切换,达到交叉业务。

AOP 面向方面的编程  涉及到代理,将业务模块化。
在方法内运行的内容前后加系统功能,可以将这些功能提取出来,放在方法前后。
运行结果是一样的。

JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。
JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理。
在调用目标方法的前后,或异常处理上加上系统功能代码。

  代理的理解:
本来客户端调用目标类
现在换成
客户端调用代理类,代理类中有个构造函数(接受handler对象)
handler是接口,可以用子类对象创建,子类中的方法invoke里
的方法调用(target)而target的内容就是各个方法的内容。
比如:你找代理的add方法,代理去找目标的add方法,而你在代理方法中
还可以加入日志方法。log(), 这样可以做一个框架,将代码以一个参数传进来。
在方法内传入一个对象,也就执行了对象的代码。
给InvocationHandler 2个对象 一个目标类的对象,一个系统功能的对象。

见ProxyTest.java类   Advice.java接口 MyAdvice类

package cn.itcast.day3;import java.lang.reflect.*;import java.util.*;/* * 获得动态类的构造方法和方法的列表。 * */public class ProxyTest {/** * @param args */public static void main(String[] args) throws Exception {// TODO Auto-generated method stubClass clazzProxy1 =Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);//先获得Proxy的字节码,(类加载器,实现的接口为接口的字节码)最后得到Class的字节码System.out.println(clazzProxy1.getName());System.out.println("----------begin constructors 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);}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());}/* * $Proxy0----------begin constructors list-----------$Proxy0(java.lang.reflect.InvocationHandler)----------begin methods list-----------hashCode()add(java.lang.Object)clear()equals(java.lang.Object)toString()contains(java.lang.Object)addAll(java.util.Collection)iterator()size()toArray()toArray([Ljava.lang.Object;)remove(java.lang.Object)isEmpty()containsAll(java.util.Collection)removeAll(java.util.Collection)retainAll(java.util.Collection)isProxyClass(java.lang.Class)getProxyClass(java.lang.ClassLoader,[Ljava.lang.Class;)getInvocationHandler(java.lang.Object)newProxyInstance(java.lang.ClassLoader,[Ljava.lang.Class;,java.lang.reflect.InvocationHandler)getClass()wait()wait(long,int)wait(long)notify()notifyAll() *  */System.out.println("-----begin create instance object开始创建实例对象-----");//clazzProxy1.newInstance();//会调用不带参数的构造方法,没有,所以得找有参数的构造方法Constructor constructor = clazzProxy1.getConstructor(InvocationHandler.class);//得传个参数,而InvocationHandler是接口,得用子类实现class MyInvocationHandler1 implements InvocationHandler{public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {// TODO Auto-generated method stubreturn null;}}//获得Collection对象Collection proxy1 = (Collection)constructor.newInstance(new MyInvocationHandler1());System.out.println(proxy1.toString());//nullproxy1.clear(); //清除集合内容,可以调用没返回值的方法//proxy1.size();//空指针异常,不可以调用有返回值的方法,因为它要去调用内部的invoke返回null,而size返回整数。Collection proxy2 = (Collection)constructor.newInstance(new MyInvocationHandler1());constructor.newInstance(new InvocationHandler(){public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {// TODO Auto-generated method stubreturn null;}});//我们先找到类,再找到实例对象,//第三种方法获得实例对象, 这里创建了一个动态类了final ArrayList target = new ArrayList();Collection proxy3 = (Collection)getProty(target,new MyAdvice());Object obj = proxy3.add("zxx");//add会去找InvocationHandler,而返回结果给了代理//obj 相当于 Object 相当于 retVal,一个传递的过程proxy3.add("lhm");proxy3.add("bxd");System.out.println(proxy3.size());System.out.println(proxy3.getClass().getName());}//给InvocationHandler 2个对象 一个目标类的对象,一个系统功能的对象。生成一个Object代理private static Object getProty(final Object target,final Advice advice) {Object proxy3 = Proxy.newProxyInstance(target.getClass().getClassLoader(),/*new Class[]{Collection.class},*/target.getClass().getInterfaces(),new InvocationHandler(){//ArrayList target = new ArrayList();//InvocationHandler接口中invoke接受三个参数 objProxy对象,add方法,“abc”参数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()+" runtime:"+(endTime-beginTime));return retVal;*///抽取了方法advice.beforeMethod(method);Object retVal =  method.invoke(target, args);advice.afterMethod(method);return retVal;}});return proxy3;}}

package cn.itcast.day3;import java.lang.reflect.Method;public interface Advice { void beforeMethod(Method method); void afterMethod(Method method);}

package cn.itcast.day3;import java.lang.reflect.Method;public class MyAdvice implements Advice {long beginTime = 0;public void afterMethod(Method method) {// TODO Auto-generated method stubSystem.out.println("从传智播客上班了");long endTime = System.currentTimeMillis();System.out.println(method.getName()+" runtime:"+(endTime-beginTime));}public void beforeMethod(Method method) {// TODO Auto-generated method stubSystem.out.println("到传智播客学习了");beginTime = System.currentTimeMillis();}}



2,实现AOP功能的封装与配置
(1)工厂类BeanFactory负责创建目标类或代理类的实例对象,并通过配置文件实现切换。
其getBean方法根据参数字符串返回一个相应的实例对象,如果参数字符串在配置文件中
对应的类名不是ProxyFactoryBean,则直接返回该类的实例对象,否则,返回该类实例对象
的getProxy方法返回的对象。
(2)BeanFactory的构造方法接收代表配置文件的输入流对象,配置文件格式如下:
#xxx=java.util.ArrayList
xxx=cn.itcast.ProxyFactoryBean
xxx.target=java.util.ArrayList
xxx.advice=cn.itcast.MyAdvice
(3)ProxyFactoryBean充当封装生成动态代理的工厂,需要为工厂类提高哪些配置参数信息?
目标
通知
(4)编写客户端应用:
编写实现Advice接口的类和在配置文件中进行配置
调用BeanFactory获取对象

思想:
(1)Object obj = BeanFactory.getBean("xxx"); 创建xxx实例对象,xxx通过配置文件修改。
如果是xxx=cn.itcast.ProxyFactoryBean 返回一个代理
再写代理的target,advice.
见BeanFactory.java  ProxyFactoryBean.java MyAdvice.java  

AopFrameworkTest.java  config.properties

package cn.itcast.day3.aopframework;import java.io.*;import java.util.*;import cn.itcast.day3.*;public class BeanFactory {Properties props = new Properties();public BeanFactory(InputStream ips){try{props.load(ips);}catch(IOException e){e.printStackTrace();}}public Object getBean(String name) {String className = props.getProperty(name);Object bean = null;try {Class  clazz = Class.forName(className); bean = clazz.newInstance();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}//如果是代理,就创建代理类,不是就产生beanif(bean instanceof ProxyFactoryBean){Object proxy = null;ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean)bean;try {Advice advice = (Advice)Class.forName(props.getProperty(name+".advice")).newInstance();Object target = Class.forName(props.getProperty(name+".target")).newInstance();proxyFactoryBean.setAdvice(advice);proxyFactoryBean.setTarget(target);proxy = ((ProxyFactoryBean)bean).getProxy();//如果是代理就产生advice target,把它们放到代理工厂里去产生代理proxy} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return proxy;}return bean;}}

package cn.itcast.day3.aopframework;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import cn.itcast.day3.*;public class ProxyFactoryBean {private Advice advice;private Object target;public Object getProxy() {// TODO Auto-generated method stub//给InvocationHandler 2个对象 一个目标类的对象,一个系统功能的对象。生成一个Object代理Object proxy3 = Proxy.newProxyInstance(target.getClass().getClassLoader(),/*new Class[]{Collection.class},*/target.getClass().getInterfaces(),new InvocationHandler(){//ArrayList target = new ArrayList();//InvocationHandler接口中invoke接受三个参数 objProxy对象,add方法,“abc”参数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()+" runtime:"+(endTime-beginTime));return retVal;*///抽取了方法advice.beforeMethod(method);Object retVal =  method.invoke(target, args);advice.afterMethod(method);return retVal;}});return proxy3;}public Advice getAdvice() {return advice;}public void setAdvice(Advice advice) {this.advice = advice;}public Object getTarget() {return target;}public void setTarget(Object target) {this.target = target;}}

package cn.itcast.day3.aopframework;import java.io.*;public class AopFrameworkTest {/** * @param args */public static void main(String[] args)throws Exception {// TODO Auto-generated method stubInputStream ips = AopFrameworkTest.class.getResourceAsStream("config.properties");Object bean = new BeanFactory(ips).getBean("xxx");System.out.println(bean.getClass().getName());}}

config.properties配置文件

xxx=java.util.ArrayList#xxx=cn.itcast.day3.aopframework.ProxyFactoryBeanxxx.advice=cn.itcast.day3.MyAdvicexxx.target=java.util.ArrayList

----------------------    android培训    java培训   期待与您交流!    ----------------------   

                         详细请查看      http://edu.csdn.net/heima


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 解完大便屁眼疼怎么办 拉大便后肛门痛怎么办 3岁宝宝肛裂怎么办 无臂人大便后怎么办 老婆移情别恋了怎么办 自己移情别恋了怎么办 嘴巴里破了变白怎么办 上嘴唇里面长泡怎么办 嘴皮里面长泡怎么办 嘴巴里经常长泡怎么办 嘴唇上长透明泡怎么办 嘴唇上长很多泡怎么办 嘴巴里长白色泡怎么办 做了漂唇起泡了怎么办 漂唇之后起泡了怎么办 漂唇后起了水泡怎么办 嘴唇起泡,弄破了怎么办 九个月的宝宝上火了怎么办 8岁儿童嘴唇起泡怎么办 宝宝嘴皮上火起泡了怎么办 上嘴唇起泡肿了怎么办 上嘴唇突然肿了怎么办? 醒来上嘴唇肿了怎么办 嘴巴突然肿了怎么办呢 下嘴唇肿起来了怎么办 上嘴唇肿了起泡怎么办 上火下嘴唇肿了怎么办 上火嘴唇都肿了怎么办 嘴唇起泡后肿了怎么办 嘴唇上有白点颗粒状怎么办 嘴唇缺了一块红怎么办 人得钩端螺旋体怎么办 脖子上有鸡皮肤怎么办 不结婚老了以后怎么办 丁克族老了怎么办知乎 2个月宝宝咳嗽怎么办 干活累的手疼怎么办 脸上长白色的癣怎么办 全身起红斑很痒怎么办 宝宝脖子红烂了怎么办 背上长红斑很痒怎么办