黑马程序员------------------代理类和AOP
2014-01-12 12:11
197 查看
----------------------
ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
代理
应用程序出了当前类能提供的功能外,有时需要一些其他的额外功能,比如安全、日志等,这时需要用代理类。
程序中的代理
(1)要为已存在的多个具有相同接口的目标类的各个方法增加一系列的系统功能,例如,异常处理,日志、计算方法等的运行时间、事务管理等等,你如何做?
(2)编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码。
(3)如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置是使用目标类还是代理类,这样以后很容易切换。譬如,想要日志功能时就配置代理类,否则配置目标类,这样增加系统功能很容易。以后运行一段时间后,又想去掉系统功能也很容易。
3.代理分为两种:静态代理和动态代理。
<AOP>
1.系统中存在交叉业务,一个交叉业务就是要切入到系统中的一个方法。
2.交叉业务的房产问题即为面向方面的编程(AOP,Aspect oriented program),AOP的目标就是要
使交叉业务模块化,可以采用将切面代码移动到原始方法的周围,这与直接在方法中编程切面代码的运行效果是一样的。
3.使用代理技术正好可以解决这种问题,代理是实现AOP功能的核心和关键技术。
.<代理模式>简单示例
动态代理技术(JVM动态代理和CGLIB库动态代理)
1.要为系统中的各种接口的类增加代理功能,那将需要太多的代理类,全部采用静态代理方式,将是一件非常麻烦的事情。(引出动态代理)
2.JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作 代理类 ,即动态代理类。
3.JVM生成的动态类必须具有一个或多个接口,所以,JVM生成的动态类(Proxy)只能用作具有相同接口的目标类的代理。
4.CGLIB库(一个开源库)可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的 类生成动态代理类,可以使用CGLIB库。
5.代理类的各个方法中通除了要调用目标的相应方法和对外返回目标返回的结果外,还可以在代理方法中的如下 四个位置加上系统功能代码:
(1).在调用目标方法之前
(2).在调用目标方法之后
(3)在调用目标方法之前或之后
(4)在处理目标方法异常的catch块中。
6.创建JVM动态代理方法:
方法一:获取动态类字节码(Class)--->用字节码获取Constructor---->用Constructor创建动态类实例
a.使用Proxy获取动态类字节码(以Collection为例)
打印clazzProxy1的所有构造方法和成员方法。
实现AOP功能的封装和配置
功能描述:建立一个BeanFactory,可以根据配置文件中的bean名称到底一个JavaBean,如果bean的名字的是“ProxyFactoryBean”则返回ProxyFactoryBean根据配置文件中的".advice"和“.target”提供的目标和Advice返回的代理类。
1.ProxyFactoryBean类代码
2.BeanFacotry代码
3.配置文件内容:
4.框架测试类:
---------------ASP.Net+Android+IOS开发、.Net培训、期待与您交流!---------------详细请查看:http://edu.csdn.net
ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
代理
应用程序出了当前类能提供的功能外,有时需要一些其他的额外功能,比如安全、日志等,这时需要用代理类。
程序中的代理
(1)要为已存在的多个具有相同接口的目标类的各个方法增加一系列的系统功能,例如,异常处理,日志、计算方法等的运行时间、事务管理等等,你如何做?
(2)编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码。
(3)如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置是使用目标类还是代理类,这样以后很容易切换。譬如,想要日志功能时就配置代理类,否则配置目标类,这样增加系统功能很容易。以后运行一段时间后,又想去掉系统功能也很容易。
3.代理分为两种:静态代理和动态代理。
<AOP>
1.系统中存在交叉业务,一个交叉业务就是要切入到系统中的一个方法。
2.交叉业务的房产问题即为面向方面的编程(AOP,Aspect oriented program),AOP的目标就是要
使交叉业务模块化,可以采用将切面代码移动到原始方法的周围,这与直接在方法中编程切面代码的运行效果是一样的。
3.使用代理技术正好可以解决这种问题,代理是实现AOP功能的核心和关键技术。
.<代理模式>简单示例
目标类: class X { void sayHello() { System.out.println("hello java"); } } 代理类: XProxy { void sayHello() { starttime; X.sayHello(); endTime; } }
动态代理技术(JVM动态代理和CGLIB库动态代理)
1.要为系统中的各种接口的类增加代理功能,那将需要太多的代理类,全部采用静态代理方式,将是一件非常麻烦的事情。(引出动态代理)
2.JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作 代理类 ,即动态代理类。
3.JVM生成的动态类必须具有一个或多个接口,所以,JVM生成的动态类(Proxy)只能用作具有相同接口的目标类的代理。
4.CGLIB库(一个开源库)可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的 类生成动态代理类,可以使用CGLIB库。
5.代理类的各个方法中通除了要调用目标的相应方法和对外返回目标返回的结果外,还可以在代理方法中的如下 四个位置加上系统功能代码:
(1).在调用目标方法之前
(2).在调用目标方法之后
(3)在调用目标方法之前或之后
(4)在处理目标方法异常的catch块中。
6.创建JVM动态代理方法:
方法一:获取动态类字节码(Class)--->用字节码获取Constructor---->用Constructor创建动态类实例
a.使用Proxy获取动态类字节码(以Collection为例)
Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class); System.out.println(clazzProxy1.getName());
打印clazzProxy1的所有构造方法和成员方法。
System.out.println("----begin constructors list-------"); /* * $Proxy0 * $Proxy0(InvocationHandler ,int) */ printConstructors(clazzProxy1); System.out.println("----begin methods list-------"); printMethods(clazzProxy1);<SPAN style="FONT-SIZE: 14px"> </SPAN>
public static void printMethods(Class clazzProxy1) { 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); } } public static void printConstructors(Class clazzProxy1) { 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); }
实现AOP功能的封装和配置
功能描述:建立一个BeanFactory,可以根据配置文件中的bean名称到底一个JavaBean,如果bean的名字的是“ProxyFactoryBean”则返回ProxyFactoryBean根据配置文件中的".advice"和“.target”提供的目标和Advice返回的代理类。
1.ProxyFactoryBean类代码
package cn.itcast.test3.aopframework; import java.io.*; import java.util.Properties; import cn.itcast.test3.Advice; public class BeanFactory { Properties prop = new Properties(); //创建对象时需要传入一个配置文件中的数据,所以需要在构造方法中接受一个参数 public BeanFactory(InputStream ips) { try { //将配置文件加载进来 prop.load(ips); } catch (IOException e) { e.printStackTrace(); } } //创建getBean方法,通过配置文件中的名字获取bean对象 public Object getBean(String name){ //从配置文件中读取类名 String className = prop.getProperty(name); Object bean = null; try { //由类的字节码获取对象 Class clazz = Class.forName(className); bean = clazz.newInstance(); } catch (Exception e) { e.printStackTrace(); } //判断bean是特殊的bean即ProxyFactoryBean还是普通的bean if(bean instanceof ProxyFactoryBean){ Object proxy = null; try { //是ProxyFactoryBean的话,强转,并获取目标和通告 ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean)bean; //获取advice和target Advice advice = (Advice)Class.forName(prop.getProperty(name + ".advice")).newInstance(); Obje 4000 ct target = Class.forName(prop.getProperty(name + ".target")).newInstance(); //设置目标和通告 proxyFactoryBean.setAdvice(advice); proxyFactoryBean.setTarget(target); //通过类ProxyFactoryBean(开发中是作为接口存在)中获得proxy对象 proxy = proxyFactoryBean.getProxy(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } //是ProxyFactoryBean的话,返回proxy对象 return proxy; } //否则返回普通bean对象 return bean; } }
2.BeanFacotry代码
import java.io.IOException; import java.io.InputStream; import java.util.Properties; import cn.itcast.day3.Advice; public class BeanFactory { Properties prop =new Properties(); public BeanFactory(InputStream inStream){ try { prop.load(inStream); } catch (IOException e) { e.printStackTrace(); } } public Object getBean(String name){ String className = prop.getProperty(name); Class clazz=null; Object bean=null; try { clazz = Class.forName(className); bean = clazz.newInstance(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } if(bean instanceof ProxyFactoryBean){ Object proxy = null; try { ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean)bean; Advice advice = (Advice) Class.forName(prop.getProperty(className+".advice")).newInstance(); Object target =Class.forName(prop.getProperty(className+".target")).newInstance(); proxyFactoryBean.setAdvice(advice); proxyFactoryBean.setTarget(target); proxy = proxyFactoryBean.getProxy(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return proxy; }else{ return bean; } } }
3.配置文件内容:
xxx=java.util.ArrayList #xxx=cn.itcast.day3.aopframework.ProxyFactoryBean xxx.advice=cn.itcast.day3.MyAdvice xxx.target=java.util.ArrayList
4.框架测试类:
import java.io.InputStream; public class AopFrameworkTest { public static void main(String[] args) { InputStream ips =AopFrameworkTest.class.getResourceAsStream("config.properties"); <span class="comment">//读取配置文件的数据 </span><span> </span> BeanFactory beanFactory = new BeanFactory(ips); Object bean =beanFactory.getBean("xxx"); System.out.println(bean.getClass().getName()); } }
---------------ASP.Net+Android+IOS开发、.Net培训、期待与您交流!---------------详细请查看:http://edu.csdn.net
相关文章推荐
- 黑马程序员_高新技术5(动态代理类,代理类的作用与原理,AOP框架应用)
- 黑马程序员——java拾遗之代理类及AOP
- 黑马程序员_泛型、类加载器、代理类、AOP
- 黑马程序员--java代理类及AOP的概念!
- 黑马程序员_高新技术五(动态代理类,代理类的作用与原理,AOP框架应用)
- 黑马程序员————代理类相关知识及AOP初步
- 【黑马程序员】java中的--------------代理类与动态代理技术
- 黑马程序员 java基础加强--代理类
- AOP代理类原理
- aop代理类的配置
- spring aop, 用spring初始化bean的时候经常报错 类型转换不过来 ,代理类$Proxy35 强制转换成被代理类失败
- 【原创】Spring-AOP代理类继承接口..
- C# 实现 Aop [Emit动态生成代理类方式]
- 黑马程序员: 基础加强(反射、类加载器、动态代理技术、AOP、InvocationHandler)
- 基于代理类ProxyFactoryBean的AOP实现---环绕通知编码实例
- 黑马程序员---代理类
- 黑马程序员--Spring Aop 面向切面编程,实现前置通知
- spring 2.5 AOP之代理类基础理解
- 黑马程序员(八) 实现Aop功能的封装和配置的小程序
- java类加载器,代理类以及Aop深入剖析