将spring ioc和aop结合

通过以下两篇文章,便可以自己做一个aop和ioc的结合,并通过xml文件进行动态的配置Spring 的aop实现原理:http://blog.csdn.net/lr222584/article/details/54755031自己写一个简单的Spring IOC容器:http://blog.csdn.net/lr222584/article/details/54744583包结
摘要由CSDN通过智能技术生成

通过以下两篇文章,便可以自己做一个aop和ioc的结合,并通过xml文件进行动态的配置

Spring 的aop实现原理:http://blog.csdn.net/lr222584/article/details/54755031

自己写一个简单的Spring IOC容器:http://blog.csdn.net/lr222584/article/details/54744583

包结构:


Beans.xml

<beans>
	<bean id="a" class="demo.myspring.impl.AImpl"/>
	<bean id="b" class="demo.myspring.impl.BImpl">
		<property name="a" bean = "a" />
	</bean>
	<bean id="c" class="demo.myspring.impl.CImpl"/>
	<!-- 生成一个动态代理对象 -->
	<aop>
		<!-- 切面类 -->
		<aspect id = "test" ref = "c">
		<!-- method要切入的方法 ,pointcut-ref为目标类,括号内为方法名 -->
			<before method = "print" pointcut-ref="demo.myspring.impl.BImpl(print)"/>
		</aspect>
	</aop>
</beans>

ClassPathXmlApplicationContext类

package demo.myspring.core;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;

import demo.myspring.BeanFactory;

public class ClassPathXmlApplicationContext implements BeanFactory {

	private Map<String, Object> beans = new HashMap<String,Object>();
	
	private Map<String,String> beansXml = new HashMap<String,String>();
	
	public ClassPathXmlApplicationContext() throws Exception{
		
		SAXBuilder sb = new SAXBuilder();//新建xml解析器
		
		Document xmlDoc = sb.build(this.getClass().getClassLoader().
					      getResourceAsStream("demo/myspring/conf/beans.xml"));//构造文档对象
		Element root = xmlDoc.getRootElement();//获取根元素
		List<Element> list = root.getChildren("bean");//获取根元素下所有名字为bean的元素
		
		//遍历所有的bean元素,并将其放入beans中
		for(int i = 0;i<list.size();i++){
			Element e = (Element)list.get(i);//获取Element元素
			String id = e.getAttributeValue("id");//获取property的id属性的值
			String clazz = e.getAttributeValue("class");//获取property的class属性的值
			beansXml.put(clazz, id);
			Object o = Class.forName(clazz).newInstance();//利用反射生成一个具体的实例
			System.out.println(" id: "+id+" class: "+clazz);
			beans.put(id, o);//将bean放入一个HashMap
			//遍历bean下的所有properyt属性,并调用setter方法,将值注入给对应的属性
			if(e.getChild("property")!=null){
				for(Element p : (List<Element>)e.getChildren("property")){
					String name = p.getAttributeValue("name");
					String bean = p.getAttributeValue("bean");
					Object beanObject = beans.get(bean);
					String methodName = "set" + name.substring(0,1).toUpperCase()+ name.substring(1);
					System.out.println("setter method name = " +methodName);
					Method m = o.getClass().getMethod(methodName,beanObject.getClass().getInterfaces()[0]);
					m.invoke(o,beanObject);//调用setter方法
				}
			}	
		}
		
		Element aop = root.getChild("aop");
		//校验容器是否使用aop,如果使用aop则用代理类替换掉beans中对应key的value
		if(aop!=null){
			Element aspect = aop.getChild("aspect");
			String id=aspect.getAttributeValue("id");
			String ref=aspect.getAttributeValue("ref");
			//从beans中获取要切入的类
			Object proxy=beans.get(ref);
			Element before = aspect.getChild("before");
			if(before!=null){
				String pointcut_ref = before.getAttributeValue("pointcut-ref");
				int subscript1 = pointcut_ref.indexOf("(");
				int subscript2 = pointcut_ref.indexOf(")");
				//目标类的名字和方法的名字
				String targetClassName = pointcut_ref.substring(0,subscript1);
				String methodName= pointcut_ref.substring(subscript1+1,subscript2);
				String targetId=beansXml.get(targetClassName);
				//获取目标类和方法
				Object target = beans.get(targetId);
				//切入的方法
				String proxyMethodName= before.getAttributeValue("method");
				//生成代理类,并替换beans中对应id的value
				DynaProxy dynaProxy = new DynaProxy();
				dynaProxy.setPointcut("before");
				dynaProxy.setTargetMethod(methodName);
				dynaProxy.setProxyMethodName(proxyMethodName);
				beans.put(targetId,dynaProxy.bind(target,proxy));
			}	
		}		
	}
	
	public Object getBean(String id) {
		return beans.get(id);
	}

}
DynaProxy类
package demo.myspring.core;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DynaProxy implements InvocationHandler {
	 //调用对象  
    private Object proxy;  
    //切入方法名
    private String proxyMethodName;
    //要切入方法的位置
    private String pointcut;
    //目标对象  
    private Object target;
    //目标方法
    private String targetMethod;
    
	public void setProxyMethodName(String proxyMethodName) {
		this.proxyMethodName = proxyMethodName;
	}
	public void setPointcut(String pointcut) {
		this.pointcut = pointcut;
	}
	public void setTargetMethod(String targetMethod) {
		this.targetMethod = targetMethod;
	}
	//返回一个target的动态代理类
	public Object bind(Object target,Object proxy){  
        this.target=target;  
        this.proxy=proxy;  
        return Proxy.newProxyInstance(this.target.getClass().getClassLoader(), this.target.getClass().getInterfaces(), this);  
    }  
    //调用target任何方法,都会调用动态代理类的invoke方法
    public Object invoke(Object proxy, Method method, Object[] args)  
            throws Throwable {  
        Object result = null;  
        //反射得到操作者的实例  
        Class clazz = this.proxy.getClass();  
        //反射得到操作者的Start方法  
        Method proxyMethod = clazz.getMethod(proxyMethodName);
       //如果是前置通知
        if("before".equals(pointcut)&&(method.getName().equals(targetMethod))){
        	proxyMethod.invoke(this.proxy,null);
        	method.invoke(this.target,null);
        }else{
        	method.invoke(this.target,null);
        }
        return result;  
    }  

}
A接口 
package demo.myspring;

public interface A {
	public void print();
}
B接口
package demo.myspring;

public interface B {
	public void print();
	public void print1();
}
C接口

package demo.myspring;

public interface C {
	public void print();
}
BeanFactory接口
public interface BeanFactory {
	public Object getBean(String id);
}
AImpl类
package demo.myspring.impl;

import demo.myspring.A;

public class AImpl implements A {

	public void print() {
		System.out.println("AImpl invoked!");
	}

}
BImpl类
package demo.myspring.impl;

import demo.myspring.A;

public class BImpl implements demo.myspring.B {
	A a;

	public void setA(A a) {
		this.a = a;
	}
	
	public void print(){
		System.out.println("BImpl invoked!");
	}
	
	public void print1(){
		System.out.println("aaaaaa");
	}
}
CImpl类
package demo.myspring.impl;

import demo.myspring.C;

public class CImpl implements C{

	public void print(){
		System.out.println("CImpl invoked!");
	}
}
Test类
package demo.myspring.test;

import demo.myspring.B;
import demo.myspring.core.ClassPathXmlApplicationContext;

public class Test {
	public static void main(String[] args) throws Exception{
		ClassPathXmlApplicationContext cpxa = new ClassPathXmlApplicationContext();
		B b = (B) cpxa.getBean("b");
		System.out.println("***********************");
		b.print();//执行b.print前,会执行CImpl的print方法
		System.out.println("***********************");
		b.print1();
	}
}
执行Test后,结果如下


这是只一个非常简单的例子,其中还有很多问题,但已经能通过配置xml文件动态实现aop的功能。



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值