黑马程序员_动态代理

来源:互联网 发布:火箭发动机 知乎 编辑:程序博客网 时间:2024/05/16 09:53
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------

动态代理技术

 

要为系统中的各种接口的类增加代理功能,那将需要太多的代理类,全部采用静态代理的方式是很麻烦的。所以JVM可以在运行时期动态的生成出类的字节码,这种动态的生成的类往往被用作代理类,即动态代理。

 

JVM生成的动态类必须实现一个或多个接口,因此,JVM生成的动态类只能用作具有相同接口的目标类的代理。

 

CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库。

 

代理类的各个方法中通常除了要调用目标的相应方法和返回目标返回的结果外,还可以在代理方法中的如下四个位置添加形同功能代码。

1、再调用目标方法前

2、在调用目标方法后

3、在调用目标方法前后

4、在处理目标方法异常的catch块中。

 

AOP(面向方面编程)

有的业务贯穿到许多个模块中,这些业务叫做模块交叉业务。

用具体代码描述交叉业务的编程问题即为面向方面的编程(AOP),AOP的,目标就是要使交叉业务模块化。可以采用将切面代码移动到原始方法周围,这与直接在方法中编写切面代码的运行效果是一样的。

代理是实现AOP功能的核心和关键技术!

 

我感觉用实现AOP功能的封装与配置这个例子可以把今天老师讲的基本概括,看了两遍终于有点懂了,下面记下以便以后更好的复习!!!

package cn.itheima.mytest.aoptest;import java.io.IOException;import java.io.InputStream;import java.lang.reflect.Proxy;import java.util.Properties;public class BeanFactory{Properties properties = new Properties();//BeanFactory的构造函数接收代表配置文件的输入流对象public BeanFactory(InputStream inputStream){try{//加载流对象properties.load(inputStream);}catch (IOException e){e.printStackTrace();}}public Object getBean(String name){Object bean = null;//确定要加载的类名String className = properties.getProperty(name);try{//获取加载类的字节码文件Class clazz = Class.forName(className);//用字节码文件创建实例对象bean = clazz.newInstance();} catch (Exception e){e.printStackTrace();}if(bean instanceof ProxyFactoryBean){ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean)bean;Object proxy = null;try{//从配置文件中获得通告和目标。Advice advice = (Advice)Class.forName(properties.getProperty(name+".advice")).newInstance();Object target = Class.forName(properties.getProperty(name+".target"));//通过setAdvice和setTarget进行设置proxyFactoryBean.setAdvice(advice);proxyFactoryBean.setTarget(target);proxy = proxyFactoryBean.getProxy();} catch (Exception e){e.printStackTrace();}return proxy;}return bean;}}package cn.itheima.mytest.aoptest;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class ProxyFactoryBean{//定义advice和target的成员变量,并获得set和get方法private Advice advice;private Object target;public Object getTarget(){return target;}public void setTarget(Object target){this.target = target;}public Advice getAdvice(){return advice;}public void setAdvice(Advice advice){this.advice = advice;}//返回值为Object的getProxy方法public Object getProxy(){//通过Proxy自身的newProxyInstance方法获得一个代理,传入三个参数分别为:Object proxy = Proxy.newProxyInstance(//1.目标的类加载器target.getClass().getClassLoader(),//2.目标类的实现的接口的集合target.getClass().getInterfaces(),//3.InvocationHandler子类的实例对象,此处是用的匿名内部类new InvocationHandler(){public Object invoke(Object proxy, Method method, Object[] args)throws Throwable{//在前后添加系统配置文件advice.beforeMethod(); Object reVal = method.invoke(target, args);advice.afterMethod();return reVal;}});return proxy;}}package cn.itheima.mytest.aoptest;//定义一个Advice接口public interface Advice{void beforeMethod();void afterMethod();}package cn.itheima.mytest.aoptest;//自定义一个类实现Advice接口,并复写接口中的方法。public class AdviceForTest implements Advice{public void beforeMethod(){System.out.println("I am before the invoked method");}public void afterMethod(){System.out.println("I am after the invoked method");}}package cn.itheima.mytest.aoptest;import java.io.InputStream;//测试AOP的主类public class TestOfAOP{public static void main(String[] args){//建立通过相对路径读取配置文件的流对象InputStream inputStream = TestOfAOP.class.getResourceAsStream("config.properties");//建立BeanFactory对象传入文件读取流对象,得到beanObject bean = new BeanFactory(inputStream).getBean("name");//打印bean所属类的名字System.out.println(bean.getClass().getName());}}配置文件:name=java.util.ArrayList#name=cn.itheima.mytest.aoptest.ProxyFactoryBeanname.advice=cn.itheima.mytest.aoptest.AdviceForTestname.target=java.util.ArrayList

 


---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
0 0