黑马程序员-代理
来源:互联网 发布:笔记本电脑如何优化 编辑:程序博客网 时间:2024/06/10 20:29
---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ---------------------
代理:
动态代理类:
JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理。
JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理。
CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库。
Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。
现在想要创建一个Proxy,根据API提供的方法,
Class clazz=Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
首先需要明确一个接口,就是要代理的接口,然后第一个参数是一个类加载器,这个类加载器一般跟这个接口的类加载器相同。
现在我想打印出这个代理类的构造函数,以及这些构造函数的参数类型
import java.lang.reflect.Constructor;import java.lang.reflect.Proxy;import java.util.Collection;public class ProxyCollection {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubClass clazz = Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);// System.out.println(clazz.getName());// 现在想打印出所有的构造函数,并且如果是有参构造函数,就让他带上参数类型StringBuilder sb = new StringBuilder();Constructor[] constructors = clazz.getConstructors();for (Constructor constructor : constructors) {sb.append(constructor.getName());sb.append('(');Class[] clazzs = constructor.getParameterTypes();for (Class clazz1 : clazzs) {sb.append(clazz1.getName()).append(',');}if (clazzs != null && clazzs.length != 0) {sb.deleteCharAt(sb.length() - 1);}sb.append(')');System.out.println(sb);}}}
打印结果:
可是我有个问题,这样做明显更简单,而且可以实现相同效果:
public static void main(String[] args) {// TODO Auto-generated method stubClass clazz = Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);// System.out.println(clazz.getName());// 现在想打印出所有的构造函数,并且如果是有参构造函数,就让他带上参数类型StringBuilder sb = new StringBuilder();Constructor[] constructors = clazz.getConstructors();for (Constructor constructor : constructors) {sb.append(constructor);System.out.println(sb);}}
打印结果:
现在把构造函数换成普通方法试试:
public static void main(String[] args) {// TODO Auto-generated method stubClass clazz = Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);// System.out.println(clazz.getName());// 现在想打印出所有的构造函数,并且如果是有参构造函数,就让他带上参数类型StringBuilder sb = new StringBuilder();Method[] methods = clazz.getMethods();for (Method method : methods) {sb.append(method);sb.append("\n");}System.out.println(sb);}
打印结果:
再用老师的方法试试:
public static void main(String[] args) {// TODO Auto-generated method stubClass clazz = Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);// System.out.println(clazz.getName());// 现在想打印出所有的构造函数,并且如果是有参构造函数,就让他带上参数类型StringBuilder sb = new StringBuilder();Method[] methods = clazz.getMethods();for (Method method : methods) {// sb.append(method);sb.append(method.getName());sb.append('(');Class[] clazzs = method.getParameterTypes();for (Class clazz1 : clazzs) {sb.append(clazz1.getName()).append(',');}if (clazzs != null && clazzs.length != 0) {sb.deleteCharAt(sb.length() - 1);}sb.append(')');sb.append("\n");}System.out.println(sb);}
打印结果:
利用动态代理创建对象:
public class ProxyCollection {/** * @param args */public static void main(String[] args) throws Exception {// TODO Auto-generated method stubClass clazz = Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);Constructor constructor = clazz.getConstructor(InvocationHandler.class);class MyInvocationHandle implements InvocationHandler {@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {// TODO Auto-generated method stubreturn null;}}Collection collection = (Collection) constructor.newInstance(new MyInvocationHandle());System.out.println(collection);}}
但是用这种方式创建的时候,感觉必须先提前知道构造函数的类型和个数。
代理详见:http://blog.csdn.net/caoyinghui1986/article/details/2450221 感觉讲的还不错,可以看看。
下面以Collection接口为列来进一步加强对动态代理的了解。
调用coll.clear()方法时,正常运行,调用add()方法时,报错,通过以上就可了解它为什么会报错,invoke()方法的返回值为null,它的返回值就是调用add()方法的返回值,add()方法本来是要返回boolean型数据的,但是现在返回的却是null,显然,null是不能转换为boolean型的。
现在我们写一种较为简单的方法:
Collection coll = (Collection) Proxy.newProxyInstance(Collection.class.getClassLoader(),new Class[] { Collection.class }, new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method,Object[] args) throws Throwable {// TODO Auto-generated method stubreturn null;}});
继续修改代码:
一般代理类在代理时,需要执行一些额外的方法,一般把这些方法定义成一个对象,而且,要被代理的类也不能用硬编码写死。
import java.lang.reflect.Constructor;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.util.ArrayList;import java.util.Collection;public class ProxyCollection1 {/** * @param args */public static void main(String[] args) throws Exception {// TODO Auto-generated method stubfinal ArrayList list = new ArrayList();Advice advice = new Actrual();Object coll = proxy(list, advice);coll.toString();}public static Object proxy(final Object target, final Advice advice) {Object coll = (Object) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method,Object[] args) throws Throwable {// TODO Auto-generated method stub// 这儿一般要做一些工作,对于这些要做的事情,我们一般把这些方法封装到一个类中,但是,我们怎么知道这个类// 中又哪儿方法,不知道有如何调用?所以我们要定义一个接口,这个类必须实现该接口advice.beforeRun();Object obj = method.invoke(target, args);// 这儿也要做一些工作advice.afterRun();return obj;}});return coll;}}
Advice接口
public interface Advice {void beforeRun();void afterRun();}
Actrual类
public class Actrual implements Advice {@Overridepublic void beforeRun() {// TODO Auto-generated method stubSystem.out.println("方法执行之前");}@Overridepublic void afterRun() {// TODO Auto-generated method stubSystem.out.println("方法执行之后");}}
实现AOP(面向方面编程)功能的封装与配置
原理:
哎,困难查重,终于做完,只是大概了解,后面还的好好看看,以下是代码:
BeanFactory类
package Spring;import java.io.IOException;import java.io.InputStream;import java.util.Properties;public class BeanFactory {InputStream ins;Properties prop = new Properties();public BeanFactory(InputStream ins) {this.ins = ins;}public Object getBean(String str) {Object obj = null;try {prop.load(ins);String str1 = prop.getProperty(str);obj = Class.forName(str1).newInstance();if (obj instanceof ProxyBeanFactory) {Advice advice = (Advice) Class.forName(prop.getProperty("xxx" + ".advice")).newInstance();Object target = Class.forName(prop.getProperty("xxx" + ".target")).newInstance();Object proxy = ((ProxyBeanFactory) obj).getProxy(target, advice);return proxy;}} catch (Exception e) {}return obj;}}
ProxyBeanFactory类
package Spring;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class ProxyBeanFactory {public Object getProxy(final Object target, final Advice advice) {Object coll = (Object) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method,Object[] args) throws Throwable {// TODO Auto-generated method stub// 这儿一般要做一些工作,对于这些要做的事情,我们一般把这些方法封装到一个类中,但是,我们怎么知道这个类// 中又哪儿方法,不知道有如何调用?所以我们要定义一个接口,这个类必须实现该接口advice.beforeRun();Object obj = method.invoke(target, args);// 这儿也要做一些工作advice.afterRun();return obj;}});return coll;}}
Config.properties配置文件
xxx=java.util.ArrayList#xxx=Spring.ProxyBeanFactoryxxx.advice=Spring.Actrualxxx.target=java.util.ArrayList
Advice类
package Spring;public interface Advice {void beforeRun();void afterRun();}
Actrual类
package Spring;public class Actrual implements Advice {@Overridepublic void beforeRun() {// TODO Auto-generated method stubSystem.out.println("方法执行之前");}@Overridepublic void afterRun() {// TODO Auto-generated method stubSystem.out.println("方法执行之后");}}AppFrameworkTest类
package Spring;import java.io.FileInputStream;import java.io.InputStream;public class AppFramworkTest {/** * @param args */public static void main(String[] args) throws Exception {// TODO Auto-generated method stubInputStream ins = new FileInputStream("config.properties");BeanFactory bf = new BeanFactory(ins);Object obj = bf.getBean("xxx");System.out.println(obj.getClass().getName());}}
---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ---------------------
- 黑马程序员 动态代理
- 黑马程序员--代理
- 黑马程序员-java-代理
- 黑马程序员_代理
- 黑马程序员_java代理
- 黑马程序员:代理
- 黑马程序员_代理
- 黑马程序员-代理
- 黑马程序员-动态代理
- 黑马程序员 动态代理
- 黑马程序员-动态代理
- 黑马程序员--动态代理
- 黑马程序员-代理
- 黑马程序员 代理学习
- 黑马程序员--动态代理
- 黑马程序员-动态代理
- 黑马程序员-----代理
- 黑马程序员---------动态代理
- WM_NCHITTEST消息
- 领导讲话常用语必备
- 复合弓
- ios框架学习
- 一个女大学生的代码学习之路(一)
- 黑马程序员-代理
- matplotlib 安装
- 使用axis1+spring+hibernate搭建webservice框架
- The Decorator Pattern 装饰者模式
- 使用TeaJs制作Rpg游戏-无耻发布
- 谨慎使用STL中的erase操作!
- 设计模式学习总结(18) 命令模式
- IOS 解决键盘挡住输入框的问题
- 在Windows下编译FFmpeg详细说明