反射最大的价值就是用来写框架,下面贴出自己的3篇代码,模拟实现SPING框架的bean工厂,IOC,AOP。当然这里重点是在利用反射实现功能,为了图方便,我用的是Properties文件,关于XML后面会有专门的博客来整理,到时候整合相关的解析XML的代码就可以了。

1,通过反射,读取配置文件来管理bean

package linkin;

import java.io.FileInputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties; //这里就是通过反射,来获得对象的工厂
public class Linkin
{
// 定义一个对象池,前面是对象名,后面是实际对象
private Map<String ,Object> objectPool = new HashMap<String ,Object>();
// 定义一个创建对象的方法,该方法只要传入一个字符串类名,程序可以根据该类名生成Java对象
private Object createObject(String clazzName) throws Exception
{
// 根据字符串来获取对应的Class对象
Class<?> clazz = Class.forName(clazzName);
// 使用clazz对应类的默认构造器创建实例
return clazz.newInstance();
}
// 该方法根据指定文件来初始化对象池,它会根据配置文件来创建对象
public void initPool(String fileName) throws Exception
{
FileInputStream fis = null;
try
{
fis = new FileInputStream(fileName);
Properties props = new Properties();
props.load(fis);
for (String name : props.stringPropertyNames())//返回此属性列表中的键集
{
// 每取出一对key-value对,就根据value创建一个对象,调用createObject()创建对象,并将对象添加到对象池中
objectPool.put(name ,createObject(props.getProperty(name)));
}
}
catch (Exception ex)
{
System.out.println("读取" + fileName + "异常");
}
finally
{
if(null != fis)
{
fis.close();
}
} }
public Object getObject(String name)
{
// 从objectPool中取出指定name对应的对象。
return objectPool.get(name);
} public static void main(String[] args)
throws Exception
{
Linkin linkin = new Linkin();
linkin.initPool("Linkin.txt");//linkin=linkin.Linkin
System.out.println(linkin.getObject("linkin"));
}
}

2,通过反射实现IOC注入功能

package linkin;

import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties; public class Linkin
{
private String name; public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
// 定义一个对象池,前面是对象名,后面是实际对象
private Map<String ,Object> objectPool = new HashMap<String ,Object>();
private Properties config = new Properties();
// 从指定属性文件中初始化Properties对象。
public void init(String fileName) throws Exception
{
FileInputStream fis = null;
try
{
fis = new FileInputStream(fileName);
config.load(fis);
}
catch (IOException ex)
{
System.out.println("读取" + fileName + "异常");
}
finally
{
if(null != fis){
fis.close();
}
}
}
// 定义一个创建对象的方法,该方法只要传入一个字符串类名,程序可以根据该类名生成Java对象
private Object createObject(String clazzName) throws Exception
{
// 根据字符串来获取对应的Class对象
Class<?> clazz =Class.forName(clazzName);
// 使用clazz对应类的默认构造器创建实例,这一行道出了javabean的精髓,为什么javabean规范中要就有一个默认的无参的构造器
return clazz.newInstance();
}
// 该方法根据指定文件来初始化对象池,它会根据配置文件来创建对象
public void initPool() throws Exception
{
for (String name : config.stringPropertyNames())
{
// 每取出一对key-value对,如果key中不包含百分号(%)
// 这个就标明是根据value来创建一个对象
// 调用createObject创建对象,并将对象添加到对象池中
if (!name.contains("%"))
{
objectPool.put(name , createObject(config.getProperty(name)));
}
}
}
// 该方法根据指定文件来初始化对象池,它会根据配置文件来创建对象
public void initProperty()throws Exception
{
for (String name : config.stringPropertyNames())
{
// 每取出一对key-value对,如果key中包含百分号(%)
// 即可认为该key是用于为对象的Field设置值,
// %前半为对象名字,后半为Field名
// 程序将调用对应的setter方法来为对应Field设置值。
if (name.contains("%"))
{
// 将配置文件中key按%分割
String[] objAndProp = name.split("%");
// 取出需要设置Field值的目标对象
Object target = getObject(objAndProp[0]);
// 该Field对应的setter方法名:set + "属性的首字母大写" + 剩下部分
String mtdName = "set" + objAndProp[1].substring(0 , 1).toUpperCase() + objAndProp[1].substring(1);
// 通过target的getClass()获取它实现类所对应的Class对象
Class<?> targetClass = target.getClass();
// 获取该属性对应的setter方法,下面这一行道出了springIOC的精髓,为什么实现XML我们每次都要提供get和set方法,除了注解的哦
Method mtd = targetClass.getMethod(mtdName , String.class);
// 通过Method的invoke方法执行setter方法,将config.getProperty(name)的属性值作为调用setter的方法的实参
mtd.invoke(target , config.getProperty(name));
}
}
}
public Object getObject(String name)
{
// 从objectPool中取出指定name对应的对象。
return objectPool.get(name);
}
public static void main(String[] args)throws Exception
{
Linkin linkin = new Linkin();
linkin.init("Linkin.txt");//linkin=linkin.Linkin
//linkin%name=LinkinPark...
linkin.initPool();
linkin.initProperty();
linkin = (Linkin) linkin.getObject("linkin");
System.out.println(linkin.getName());
}
}

3,通过反射实现AOP框架,并且跑了代理,(人为可以控制跑不跑代理)。

package linkin;

import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties; public class Linkin implements Person
{
private String name; public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
//定义这个方法来作为测试
public void test()
{
System.out.println("这里是原始的方法");
}
// 定义一个对象池,前面是对象名,后面是实际对象
private Map<String ,Object> objectPool = new HashMap<String ,Object>();
private Properties config = new Properties();
// 从指定属性文件中初始化Properties对象。
public void init(String fileName) throws Exception
{
FileInputStream fis = null;
try
{
fis = new FileInputStream(fileName);
config.load(fis);
}
catch (IOException ex)
{
System.out.println("读取" + fileName + "异常");
}
finally
{
if(null != fis){
fis.close();
}
}
}
// 定义一个创建对象的方法,该方法只要传入一个字符串类名,程序可以根据该类名生成Java对象
private Object createObject(String clazzName) throws Exception
{
// 根据字符串来获取对应的Class对象
Class<?> clazz = Class.forName(clazzName);
// 使用clazz对应类的默认构造器创建实例,这一行道出了javabean的精髓,为什么javabean规范中要就有一个默认的无参的构造器
return clazz.newInstance();
}
// 该方法根据指定文件来初始化对象池,它会根据配置文件来创建对象
public void initPool() throws Exception
{
for (String name : config.stringPropertyNames())
{
// 每取出一对key-value对,如果key中不包含百分号(%),这个就标明是根据value来创建一个对象,调用createObject创建对象,并将对象添加到对象池中
// 如果他是我们自己定义的LinkinProxy,就说明这里是跑代理的,不然就是不跑代理的
String className = config.getProperty(name);
if (!name.contains("%") && !name.contains("."))
{
Object bean = createObject(className);
if(bean instanceof LinkinProxy)
{
LinkinProxy linkinProxyBean = (LinkinProxy) bean;
LinkinAdvice linkinAdvice = (LinkinAdvice) createObject(config.getProperty(name + ".advice"));
Object target = createObject(config.getProperty(name + ".target"));
initProperty(target);
linkinProxyBean.setLinkinAdvice(linkinAdvice);
linkinProxyBean.setTarget(target);
bean = linkinProxyBean.getProxyBean();
}
else
{
initProperty(bean);
}
objectPool.put(name , bean);
}
}
}
// 该方法根据指定文件来初始化对象池,它会根据配置文件来创建对象
public void initProperty(Object target)throws Exception
{
for (String name : config.stringPropertyNames())
{
// 每取出一对key-value对,如果key中包含百分号(%)
// 即可认为该key是用于为对象的Field设置值,
// %前半为对象名字,后半为Field名
// 程序将调用对应的setter方法来为对应Field设置值。
if (name.contains("%"))
{
// 将配置文件中key按%分割
String[] objAndProp = name.split("%");
// 取出需要设置Field值的目标对象,这里加一个控制,如果他是代理的话,就不能从池里面去取le
//Object target = getObject(objAndProp[0]);
// 该Field对应的setter方法名:set + "属性的首字母大写" + 剩下部分
String mtdName = "set" + objAndProp[1].substring(0 , 1).toUpperCase() + objAndProp[1].substring(1);
// 通过target的getClass()获取它实现类所对应的Class对象。
Class<?> targetClass = target.getClass();
// 获取该属性对应的setter方法,下面这一行道出了springIOC的精髓,为什么实现XML我们每次都要提供get和set方法,除了注解的哦
Method mtd = targetClass.getMethod(mtdName , String.class);
// 通过Method的invoke方法执行setter方法,将config.getProperty(name)的属性值作为调用setter的方法的实参
mtd.invoke(target , config.getProperty(name));
}
}
}
public Object getObject(String name)
{
// 从objectPool中取出指定name对应的对象。
return objectPool.get(name);
}
public static void main(String[] args)throws Exception
{
Linkin linkin = new Linkin();
linkin.init("Linkin.txt");
linkin.initPool();
Person huhu = (Person) linkin.getObject("XXX");
System.out.println(huhu.getClass());
huhu.test();
}
} class LinkinProxy
{
private Object target;//原始对象
private LinkinAdvice linkinAdvice;//服务 public LinkinAdvice getLinkinAdvice()
{
return linkinAdvice;
} public void setLinkinAdvice(LinkinAdvice linkinAdvice)
{
this.linkinAdvice = linkinAdvice;
} public Object getTarget()
{
return target;
} public void setTarget(Object target)
{
this.target = target;
} public Object getProxyBean()
{
LinkinInvocationHandler linkinInvocationHandler = new LinkinInvocationHandler();
linkinInvocationHandler.setTarget(target);
linkinInvocationHandler.setLinkinAdvice(linkinAdvice);
Object proxyBean = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
linkinInvocationHandler);
return proxyBean;
}
} //定义接口
interface Person
{
void test();
}
interface LinkinAdvice
{
public void test();
public void test1();
}
//定义服务1
class LinkinAdvice1 implements LinkinAdvice
{
public void test()
{
System.out.println("这里是第1个通用的方法。。。");
}
public void test1()
{
System.out.println("这里是第2个通用的方法");
}
}
//定义服务2
class LinkinAdvice2 implements LinkinAdvice
{
public void test()
{
System.out.println("这里是第3个通用的方法。。。");
}
public void test1()
{
System.out.println("这里是第4个通用的方法");
}
} class LinkinInvocationHandler implements InvocationHandler
{
private Object target; private LinkinAdvice linkinAdvice;//服务 public Object getTarget()
{
return target;
} public void setTarget(Object target)
{
this.target = target;
} public LinkinAdvice getLinkinAdvice()
{
return linkinAdvice;
} public void setLinkinAdvice(LinkinAdvice linkinAdvice)
{
this.linkinAdvice = linkinAdvice;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
linkinAdvice.test();
Object result = method.invoke(target, args);
linkinAdvice.test1();
return result;
} }
#一下配置文件的说明:要是直接生成原始对象就直接指定全限定类名就好了,要是想跑代理就指定下面那个名字,然后设置服务和原始对象#
#下面的属性注入模拟了IOC功能,不管是代理对象还是原始对象,都可以把这个属性值注入,原始对象就是注入原始对象,代理对象就是注入到被代理的那个原始对象中#
#XXX=linkin.Linkin
##以这个作为控制,要是得到的类放完反射属于这个类,那么就认为是要代理,不然就是不代理#
XXX=linkin.LinkinProxy
#模拟了属性注入,XML是通过自己的标签,这里我自己使用“%”模拟了下#
XXX%name=LinkinPark...
#这里是代理对象的服务,也就是AOP中插入的通用服务代码,可以随便切换,自己定义个服务,这里配上就可以用了#
XXX.advice=linkin.LinkinAdvice2
#这里就是上面那个代理类的原始对象#
XXX.target=linkin.Linkin



反射应用--IOC和AOP的更多相关文章

  1. Spring的IOC和AOP之深剖

    今天,既然讲到了Spring 的IOC和AOP,我们就必须要知道 Spring主要是两件事: 1.开发Bean:2.配置Bean.对于Spring框架来说,它要做的,就是根据配置文件来创建bean实例 ...

  2. spring - ioc和aop

    1.程序中为什么会用到spring的ioc和aop 2.什么是IOC,AOP,以及使用它们的好处,即详细回答了第一个问题 3.原理 关于1: a:我们平常使用对象的时候,一般都是直接使用关键字类new ...

  3. 【转】spring - ioc和aop

    [转]spring - ioc和aop 1.程序中为什么会用到spring的ioc和aop 2.什么是IOC,AOP,以及使用它们的好处,即详细回答了第一个问题 3.原理 关于1: a:我们平常使用对 ...

  4. Spring 的IOC和AOP总结

    Spring 的IOC和AOP IOC 1.IOC 许多应用都是通过彼此间的相互合作来实现业务逻辑的,如类A要调用类B的方法,以前我们都是在类A中,通过自身new一个类B,然后在调用类B的方法,现在我 ...

  5. Spring IOC、AOP、Transaction、MVC小结

    1.IOC.AOP:把对象交给Spring进行管理,通过面向切面编程来实现一些“模板式”的操作,使得程序员解放出来,可以更多的关注业务实现.                             - ...

  6. 【Java】模拟Sping,实现其IOC和AOP核心(二)

    接着上一篇,在上一篇完成了有关IOC的注解实现,这一篇用XML的方式实现IOC,并且完成AOP. 简易的IOC框图 注解的方式实现了左边的分支,那么就剩下右边的XML分支: XmlContext:这个 ...

  7. 【Java】模拟Sping,实现其IOC和AOP核心(一)

    在这里我要实现的是Spring的IOC和AOP的核心,而且有关IOC的实现,注解+XML能混合使用! 参考资料: IOC:控制反转(Inversion of Control,缩写为IoC),是面向对象 ...

  8. Spring IOC AOP的原理 如果让你自己设计IOC,AOP如何处理(百度)

    百度的面试官问,如果让你自己设计一个IOC,和AOP,如何设计, 我把IOC的过程答出来了,但是明显不对, (1) IOC 利用了反射,自己有个id,classtype,hashmap,所有的功能都在 ...

  9. 详谈 Spring 中的 IOC 和 AOP

    这篇文章主要讲 Spring 中的几个点,Spring 中的 IOC,AOP,下一篇说说 Spring 中的事务操作,注解和 XML 配置. Spring 简介 Spring 是一个开源的轻量级的企业 ...

随机推荐

  1. 分享一个大神自己的blog

    std::sort() 详解 http://feihu.me/blog/ C++11 新特性 http://blog.guoyb.com/2016/09/19/cpp11-all/ unity3d 相 ...

  2. Windows内核函数

    字符串处理 在驱动中一般使用的是ANSI字符串和宽字节字符串,在驱动中我们仍然可以使用C中提供的字符串操作函数,但是在DDK中不提倡这样做,由于C函数容易导致缓冲区溢出漏洞,针对字符串的操作它提供了一 ...

  3. 常见的DBCP连接池配置

    项目中使用mybatis出现一个问题,项目刚启动时,查询项目列表是ok的,过上一段时间之后,再次查询项目列表,查询失败,初步判断是因为mysql的连接问题,最后查阅资料,发现是连接池中的连接失效,导致 ...

  4. java中重载一定在一个类里面吗?

    虽然这些概念在翻译成中文的过程中,有很多不同的翻译方式但本质上只有两种说法,就是Override和Overload其中,Overload一般都被翻译成重载而Override的翻译就乱七八糟了,所谓覆盖 ...

  5. JavaScript图片库(简单的应用案例)

    这个图片库小例子的效果如图所示,点击网页上某个图片链接时你将看到两种效果:占位符图片呗替换成这个链接所指向的图片,同时描述性文字也被替换为这个链接的title属性值.     利用一个简单的图片库应用 ...

  6. Java_web学习(一) jdk配置

    1.下载好jdk1.8.0版本或以上版本 2.配置JAVA_HOME,CLASSPATH,PATH 其中JAVA_HOME必须的 2.1   JAVA_HOME=E:\java\jdk1.8.0_77 ...

  7. gulp不完全入门教程

    引言 gulp 是基于 Nodejs 的自动任务运行器,能自动化地完成javascript/coffee/sass/less/html/image/css等文件的的测试.检查.合并.压缩.格式化.浏览 ...

  8. bzoj:1687;poj 2434:[Usaco2005 Open]Navigating the City 城市交通

    Description A dip in the milk market has forced the cows to move to the city. The only employment av ...

  9. poj1258prim算法

    /*poj 1258 *题意:有若干个农场,现需要将各个农场用光纤连接起来,各个农场之间连接的光纤长度也许不同, *要求求出使得将所有农场连接起来的最短光线长度 *算法分析:使用矩阵将各个农场之间的光 ...

  10. Matrix Chain Multiplication(表达式求值用栈操作)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1082 Matrix Chain Multiplication Time Limit: 2000/100 ...