跳到正文

【java进阶】如何实现类似于Spring的可配置框架

首先,我们来定义一个Bean工厂【BeanFactory.java】 package com.java.aopframework; import java.io.*; import java.util.Properties; import com.java.day3.Advice; //这个类是纯粹地去创建一个JavaBean public class BeanFactory { Properties properties = new Properties(); //利用配置文件构造 public BeanFactory(InputStream ips) { try { properties.load(ips); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } public Object getBean(String name) { //System.out.println(""+name); //c从配置文件中获取类名称 String className = properties.getProperty(name); //com.java.aopframework.ProxyFactoryBean Class clazz = null; Object bean = null; System.out.println(""+className); try { //获取类名称 clazz = Class.forName(className); System.out.println(""+clazz); //获取javaBean,【注意】JavaBean必须要有一个不带参数的构造函数 bean = clazz.newInstance(); //如果是这种类型的JavaBean if (bean instanceof ProxyFactoryBean) { //如果已经存在这个类, 就去获取代理 ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean)bean; //Advice advice = ((Advice) properties.get(name+".advice")).getClass().newInstance(); //Object target = ((Object) properties.get(name+".target")).getClass().newInstance(); System.out.println(properties.getProperty(name+".advice")); //com.java.day3.MyAdvice System.out.println(properties.getProperty(name+".target")); //java.util.ArrayList String s_advice = properties.getProperty(name+".advice"); String s_target = properties.getProperty(name+".target"); Advice advice = (Advice) Class.forName(s_advice).newInstance(); Object target = (Object)Class.forName(s_target).newInstance(); proxyFactoryBean.setAdvice(advice); proxyFactoryBean.setTarget(target); Object proxy = proxyFactoryBean.getProxy(); //System.out.println(properties.getProperty(name+".advice")+"\t"+properties.get(name+".target")+"\t"+proxy); return proxy; } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } //返回目标 return bean; } } 然后,再来一个代理Bean工厂 【ProxyFactoryBean.java】 package com.java.aopframework; import java.lang.reflect.*; import com.java.day3.Advice; public class ProxyFactoryBean { // 定义两个私有变量 private Object target; private Advice advice; 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; } public Object getProxy() { // TODO Auto-generated method stub // 直接创建动态类及其实例对象 Object proxy = Proxy.newProxyInstance(target.getClass() .getClassLoader(), /* new Class { Collection.class }, */ target.getClass().getInterfaces(), new InvocationHandler() { // 这也是匿名内部类 @Override public Object invoke(Object proxy, Method method, Object args) throws Throwable { // 使用一个新对象来实现方法 advice.beforeMethod(method); Object retVal = method.invoke(target, args); advice.afterMethod(method); return retVal; } }); return proxy; } } 再来一个测试类 【AopFrameWorkTest.java】 package com.java.aopframework; import java.io.*; import java.util.ArrayList; import java.util.Collection; public class AopFrameWorkTest { public static void main(String args) { InputStream ips = AopFrameWorkTest.class.getResourceAsStream("configure.properties"); Object bean = new BeanFactory(ips).getBean("XXX"); //class com.sun.proxy.$Proxy0 com.sun.proxy.$Proxy0 System.out.println(bean.getClass()+"\t"+bean.getClass().getName()); ArrayList arrlist = (ArrayList)bean; arrlist.add(10); arrlist.add(50); System.out.println(arrlist.size()); } } 定义我的配置文件 【configure.properties】 XXX=java.util.ArrayList #XXX= com.java.aopframework.ProxyFactoryBean XXX.advice= com.java.day3.MyAdvice XXX.target=java.util.ArrayList 总结 一个典型的动态代理创建对象过程可分为以下四个步骤: 1、通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(...); 2、通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类 Class clazz = Proxy.getProxyClass(classLoader,new Class{...}); 3、通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型 Constructor constructor = clazz.getConstructor(new Class{InvocationHandler.class}); 4、通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入 Interface Proxy = (Interface)constructor.newInstance(new Object (handler)); 为了简化对象创建过程,Proxy类中的newInstance方法封装了2~4,只需两步即可完成代理对象的创建。 生成的ProxySubject继承Proxy类实现Subject接口,实现的Subject的方法实际调用处理器的invoke方法,而invoke方法利用反射调用的是被代理对象的的方法(Object result=method.invoke(proxied,args))

评论

填写昵称与邮箱即可评论,无需登录。

推荐阅读