**spring AOP 动态代理 原理分析** 程序中的代理 1)要为程序中已经存在的多个具有相同接口的目标类的各个方法 添加一些系统功能,例如,异常处理、日志、计算方法的运行时间。 2)编写一个与目标类实现相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在每个方法上加上系统功能 的代码。 3)如果采用工厂模式和配置文件的方式进行管理。则不需要修改客户端程序,在配置文件中配置是使用目标类、还是代理类、这样以后很容易切换、譬如,想用日志功能时就配置代理类、否则配置目标类,这样增加系统功能很容易,以后运行一段时间后,又想去掉系统功能也很容易。以下代码是模拟spring AOP原理写的一个例子1、创建一个工厂类FactoryBean,里面提供获取bean的方法,方法中判断bean是否为代理bean,如果是则向代理bean中相应的系统逻辑
```package aopFrameWork;import java.io.IOException;import java.io.InputStream;import java.util.Properties;/** * * @ClassName: FactoryBean * @Description: 工厂类(成员对象Properties用来读取文件后缀为.properties文件通过流的形式)* 通过面向对象的设计思想,读取不同的配置文件都可以通过这个FactoryBean* @author ZhangGuangxi* @date 2015年11月15日 下午3:01:38 * */public class FactoryBean { private Properties prop = new Properties(); public FactoryBean(InputStream inputstream) { try { prop.load(inputstream); } catch (IOException e) { e.printStackTrace(); } } public Object getBean(String name){ String clazzName = prop.getProperty(name); Object object = null ; try { Class<?> clazz = Class.forName(clazzName); object = clazz.newInstance(); if(object instanceof ProxyFactoryBean){ Object proxy = null; ProxyFactoryBean proxyFactoryBean= (ProxyFactoryBean)object; Advice advice = (Advice)Class.forName(prop.getProperty(name+".advice")).newInstance(); Object target = Class.forName(prop.getProperty(name+".target")).newInstance(); proxyFactoryBean.setAdvice(advice); proxyFactoryBean.setTarget(target); proxy = proxyFactoryBean.getProxy(); return proxy; } } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { e.printStackTrace(); } return object; }}```2、创建一个代理工厂类ProxyFacotryBean,里面有两个成员变量一个是目标对象target另外一个系统功能类advice,该类中还提供了一个方法getProxy,该方法通过jdk中提供的类Proxy来创建一个代理对象newProxyInstance方法,该方法需要传递三个参数a:目标类所需加载器、目标类实现的接口,并且需要InVocationHandler的实现类作为参数,该实现类中需要重写父类的invok方法,并在该方法中实现需要植入的系统代码,可以在调用目标方法前后植入所需代码
```package aopFrameWork;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;/** * * @ClassName: ProxyFactoryBean * @Description: 代理工厂类(顾名思义就是生产"代理类"的工厂),里面有两个成员变量,通知(系统功能) 目标对象(被代理对象)* @author ZhangGuangxi* @date 2015年11月15日 下午3:26:13 * */public class ProxyFactoryBean { private Advice advice; private Object target; 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; } public Object getProxy(){ Object object = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { advice.beforeMethod(method); Object object = method.invoke(target, args); advice.afterMethod(method); return object; } }); return object; }}```创建系统功能的接口Advice
```package aopFrameWork;import java.lang.reflect.Method;public interface Advice { void beforeMethod(Method method); void afterMethod(Method method);}``` 创建系统接口功能的实现类MyAdvice
```package aopFrameWork;import java.lang.reflect.Method;public class MyAdvice implements Advice{ long beginTime =0; @Override public void beforeMethod(Method method) { System.out.println("在深圳找到工作,准备上班了"); long endTime = System.currentTimeMillis(); System.out.println(method.getName()+"running time of"+(endTime - beginTime)); } @Override public void afterMethod(Method method) { System.out.println("来深圳找工作了"); beginTime = System.currentTimeMillis(); }}``` 创建类相关信息的配置文件config.properties
```#xxx=java.util.ArrayListxxx=aopFrameWork.ProxyFactoryBeanxxx.advice=aopFrameWork.MyAdvicexxx.target=java.util.ArrayList```创建测试AioFraneWorkTest类进行测试
```package aopFrameWork;import java.util.Collection;public class AopFrameWorkTest { private static final String E = null; public static void main(String[] args) { FactoryBean factoryBean = new FactoryBean(AopFrameWorkTest.class.getResourceAsStream("config.properties")); Object bean = factoryBean.getBean("xxx"); ((Collection)bean).clear(); }}```
spring AOP(动态代理)解析
最新推荐文章于 2024-05-30 17:54:18 发布