这几天重新把传智播客的黎活明的Spring2.5的教程学习了一遍,跟着上面的解析Spring的过程跟着制作了一个简单的Spring IOC和Spring AOP,先在贴上来给大家参考一下。

1:管理Bean和依赖注入 配制文件bean.xml格式如下模板所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.ganggang.com/beans"> <bean id="personDao" class="com.ganggang.dao.impl.PersonDaoImpl"> </bean>
<bean id="personService" class="com.ganggang.service.impl.PersonServiceImpl">
<property name="no" value="0704685003"/>
</bean>
</beans>

  用一个名为XmlApplication的类从bean.xml中读取相应的bean的配制信息并根据需要返回想要实例化的bean的实例对象。

public class XmlApplication {
private List<BeanDefinition> beans=new ArrayList<BeanDefinition>();
private Map<String,Object> objs=new HashMap<String, Object>();
public XmlApplication(String file){
this.readXml(file);
this.instance();
this.annotationInject();
this.injectObject();
................ }
}

  XmlApplication对象实例化时,先用readXml函数读取bean.xml中的bean配置信息,将每个bean实例化成BeanDefinition对象并存储在名为beans的链表中,BeanDefinition定义如下:

public class BeanDefinition {
private String id;
private String className;
private List<PropertyDefinition> propertys=new ArrayList<PropertyDefinition>(); public BeanDefinition(String id, String className) {
this.id = id;
this.className = className;
}
...........getter和setter方法 }

  BeanDefinition中的propertys用来表示每个bean中的属性,每个属性即是一个PropertyDefinition型对象,PropertyDefinition定义如下:

public class PropertyDefinition {
private String name;
private String ref;
private String value; public PropertyDefinition(String name, String ref,String value) {
this.name = name;
this.ref = ref;
this.value=value;
}
.................getter和setter方法
}

  readXml函数的代码如下:

private void readXml(String file) {
SAXReader saxReader = new SAXReader();
Document document=null;
try{
URL xmlpath = this.getClass().getClassLoader().getResource(file);
document = saxReader.read(xmlpath);
Map<String,String> nsMap = new HashMap<String,String>();
nsMap.put("ns","http://www.ganggang.com/beans");//加入命名空间
XPath xsub = document.createXPath("//ns:beans/ns:bean");//创建beans/bean查询路径
xsub.setNamespaceURIs(nsMap);//设置命名空间
List<Element> beanss = xsub.selectNodes(document);//获取文档下所有bean节点
for(Element element: beanss){
String id = element.attributeValue("id");//获取id属性值
System.out.println(id);
String clazz = element.attributeValue("class"); //获取class属性值
BeanDefinition beanDefine = new BeanDefinition(id, clazz);
//开始处理property
XPath propertysub=element.createXPath("ns:property");
propertysub.setNamespaceURIs(nsMap);
List<Element> props=propertysub.selectNodes(element);
for(Element e:props){
String name=e.attributeValue("name");
String ref=e.attributeValue("ref");
String val=e.attributeValue("value");
PropertyDefinition propertyDefinition=new PropertyDefinition(name,ref,val);
beanDefine.getPropertys().add(propertyDefinition);
System.out.println("name:"+name+";value:"+val);
}
//除了你property完毕
beans.add(beanDefine);
}
}catch(Exception e){
e.printStackTrace();
}
}

  然后,XmlApplication再调用instance方法实例化beans中的bean,并将每个bean对象存储在map型的objs中,objs中的key即为每个bean的id。

private void instance() {
for(BeanDefinition bean:beans){
try {
objs.put(bean.getId(), Class.forName(bean.getClassName()).newInstance());
System.out.println(bean.getId());
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }

  最后进行依赖注入,本程序同时支持注解注入和xml配制文件注入,根据实际需要选择注入方式。其中annotationInject函数执行注解注入,injectObject函数执行配制文件注入。代码如下:

private void annotationInject() {
for(String beanName:objs.keySet()){
Object bean=objs.get(beanName);
if(bean!=null){
try {
PropertyDescriptor[] ps=Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
for(PropertyDescriptor properdesc:ps){
Method setter=properdesc.getWriteMethod();
if(setter!=null&&setter.isAnnotationPresent(Resource.class)){
Resource resource=setter.getAnnotation(Resource.class);
Object value=null;
if(resource.name()!=null&&!"".equals(resource.name())){
value=objs.get(resource.name()); }else{
value=objs.get(properdesc.getName());
if(value==null){
for(String key:objs.keySet()){
if(properdesc.getPropertyType().isAssignableFrom(objs.get(key).getClass())){
value=objs.get(key);
break;
}
}
}
}
setter.setAccessible(true);
setter.invoke(bean, value);
}
}
Field[] fields= bean.getClass().getDeclaredFields();
for(Field field:fields){
if(field.isAnnotationPresent(Resource.class)){
Resource resource=field.getAnnotation(Resource.class);
Object value=null;
if(resource.name()!=null&&!"".equals(resource.name())){
value=objs.get(resource.name()); }else{
value=objs.get(field.getName());
if(value==null){
for(String key:objs.keySet()){
if(field.getType().isAssignableFrom(objs.get(key).getClass())){
value=objs.get(key);
break;
}
}
}
}
field.setAccessible(true);
field.set(bean, value);
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} }
private void injectObject() {
for(BeanDefinition beanDefinition:beans){
Object bean=objs.get(beanDefinition.getId());
if(bean!=null){
try {
PropertyDescriptor[] ps=Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
for(PropertyDefinition propertyDefinition:beanDefinition.getPropertys()){
for(PropertyDescriptor properdesc:ps){
if(propertyDefinition.getName().equals(properdesc.getName())){
Method setter= properdesc.getWriteMethod();
if(setter!=null){
Object value=null;
if(propertyDefinition.getRef()!=null&&!"".equals(propertyDefinition.getRef().trim())){
value=objs.get(propertyDefinition.getRef()); }else{
value=ConvertUtils.convert(propertyDefinition.getValue(), properdesc.getPropertyType());
}
setter.setAccessible(true);
setter.invoke(bean, value);
}
break;
}
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
} }

  

注入函数遍历beans中的每一个bean,如果其中有相应的property需要注入,就从objs中取得相应的实例对象注入。

XmlApplication含有一个获取相应bean的实力的函数,名为getObj,代码如下:

public Object getObj(String id){
return objs.get(id);
}

  

您只需在bean.xml中配制相应的bean就可以实例化一个XmlApplication对象调用getObj函数控制反转出相应的Bean的实例。

2.动态代理实现AOP

有两种,JDKProxy实现动态代理和CGLib实现。

JDKProxy实现的代码如下:

public class JDKProxyFactory implements InvocationHandler{
private Object targetObject; public Object createProxyInstance(Object targetObject){
this.targetObject=targetObject;
return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(),
this.targetObject.getClass().getInterfaces(),
this); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
PersonServiceBean bean=(PersonServiceBean)this.targetObject;
Object result=null;
if(bean.getUser()!=null){
result=method.invoke(targetObject, args);
}
return result;
} }

  CGLib实现的代码如下:

public class CGligProxyFactory implements MethodInterceptor{
private Object targetObject; public Object createProxyInstance(Object targetObject){
this.targetObject=targetObject;
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(this.targetObject.getClass());
enhancer.setCallback(this);
return enhancer.create();
} public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
PersonServiceBean bean=(PersonServiceBean)this.targetObject;
Object result=null;
if(bean.getUser()!=null){
result=methodProxy.invoke(targetObject, args);
}
return null;
}

  

Spring解析实践的更多相关文章

  1. Spring MVC 实践 - Component

    Spring MVC 实践 标签 : Java与Web Converter Spring MVC的数据绑定并非没有任何限制, 有案例表明: Spring在如何正确绑定数据方面是杂乱无章的. 比如: S ...

  2. Spring MVC 实践 - Base

    Spring MVC 实践 标签 : Java与Web Spring Web MVC Spring-Web-MVC是一种基于请求驱动的轻量级Web-MVC设计模式框架, Spring MVC使用MVC ...

  3. Spring+MyBatis实践—MyBatis数据库访问

    关于spring整合mybatis的工程配置,已经在Spring+MyBatis实践—工程配置中全部详细列出.在此,记录一下几种通过MyBatis访问数据库的方式. 通过sqlSessionTempl ...

  4. Spring Boot实践——Spring AOP实现之动态代理

    Spring AOP 介绍 AOP的介绍可以查看 Spring Boot实践——AOP实现 与AspectJ的静态代理不同,Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改 ...

  5. Spring Boot实践——AOP实现

    借鉴:http://www.cnblogs.com/xrq730/p/4919025.html     https://blog.csdn.net/zhaokejin521/article/detai ...

  6. 曹工说Spring Boot源码(7)-- Spring解析xml文件,到底从中得到了什么(上)

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  7. 曹工说Spring Boot源码(8)-- Spring解析xml文件,到底从中得到了什么(util命名空间)

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  8. 曹工说Spring Boot源码(9)-- Spring解析xml文件,到底从中得到了什么(context命名空间上)

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  9. # 曹工说Spring Boot源码(10)-- Spring解析xml文件,到底从中得到了什么(context:annotation-config 解析)

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

随机推荐

  1. Hibernated的sql查询

    记录一下学习Hibernate的心得 1.为什么HIbernate会支持原生态的sql查询? HQL查询语句虽然方便我们查询,但是基于HQL的查询会将查询出来的对象保存到hibernate的缓存当中, ...

  2. tttttabs

    <div id="fil-page" class="fil-page"> <div class="fil-container&quo ...

  3. Java--剑指offer(5)

    21.输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对 ...

  4. 89c51中断入口地址表

    中断源   中断入口地址 外部中断0 0003H 定时器/计数器T0 000BH 外部中断1 0013H 定时器/计数器T1 001BH 串行口中断   0023H

  5. iOS开发小技巧--纯代码自定义cell

    纯代码自定义cell 自定义cell的步骤(每个cell的高度不一样,每个cell里面显示的内容也不一样) 1.新建一个继承自UITableViewCell的子类 2.在initWithStyle:方 ...

  6. 【BZOJ 2843】极地旅行社

    复习一下$LinkCutTree$的模板. #include<cstdio> #include<cstring> #include<algorithm> #defi ...

  7. 网络流 最大流HDU 3549

    //////////在这幅图中我们首先要增广1->2->4->6,这时可以获得一个容量为2的流,但是如果不建立4->2反向弧的话,则无法进一步增广,最终答案为2,显然是不对的, ...

  8. mysql分表的三种方法

    先说一下为什么要分表当一张的数据达到几百万时,你查询一次所花的时间会变多,如果有联合查询的话,我想有可能会死在那儿了.分表的目的就在于此,减小数据库的负担,缩短查询时间.根据个人经验,mysql执行一 ...

  9. spring3使用task:annotation-driven开始定时

    先看一个案例 package com.jCuckoo.demo; import java.text.SimpleDateFormat; import java.util.Date; import or ...

  10. 绑定: 通过 Binding 绑定对象, 通过 x:Bind 绑定对象, 通过 Binding 绑定集合, 通过 x:Bind 绑定集合

    背水一战 Windows 10 之 绑定 通过 Binding 绑定对象 通过 x:Bind 绑定对象 通过 Binding 绑定集合 通过 x:Bind 绑定集合 示例1.演示如何通过 Bindin ...