博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Autumn,仿Spring IOC/AOP集成开发框架
阅读量:5893 次
发布时间:2019-06-19

本文共 23987 字,大约阅读时间需要 79 分钟。

  hot3.png

为了能更为深入理解Spring原理,知道怎么用还不如会自己做,于是便动手完成了这个集成框架。功能点仿照Spring,包括IOC中的注入、延迟加载、装配集合等等一系列功能,AOP是采用jdk动态代理实现的,没用CGLIB,因此,被代理的对象必须继承某个接口。

源代码主要为:

ConfigManager.java    负责解析xml、装配bean、获取bean等操作,是框架最重要的类。

ParserHelper.java    辅助XML解析的类。

ProxyHandler.java    代理类,用于支持AOP功能。

ProceedingJoinPoint.java    为了能够实现代理链,封装了Method、Object、args对象以及execute()方法。

AspectInfo.java    切面信息对象。

autumn.dtd    DTD文件,用于约束配置文件语法。

 

源码如下:

ConfigManager.java

package cn.seu.bingluo.ioc;import java.lang.reflect.InvocationTargetException;/* * By Bingluo 2012.8.17 * cose.seu.edu.cn */public class ConfigManager {	// 存放dom	private Document dom;	private Element root;	// 从配置中生成的bean放入map中	private HashMap
beans = new HashMap
(); // 在构造函数时,初始化dom树 public ConfigManager(String xmlUrl) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setIgnoringElementContentWhitespace(true); DocumentBuilder db; try { db = factory.newDocumentBuilder(); dom = db.parse(xmlUrl); dom.normalize(); root = dom.getDocumentElement(); System.out.println("IOC/AOP初始化开始..."); initBeans(); System.out.println("IOC/AOP初始化结束..."); } catch (Exception e) { e.printStackTrace(); } } // 初始化配置文件中所有非懒加载的bean private void initBeans() { for (Node node = root.getFirstChild(); node != null; node = node .getNextSibling()) { // 延迟加载Bean if (node.getNodeName().equals("bean") && ((Element) node).hasAttribute("lazy-init") && ((Element) node).getAttribute("lazy-init") .equals("true")) continue; else if (node.getNodeType() == Node.ELEMENT_NODE && node.getNodeName().equals("bean")) // 普通bean // 创建后,存入map中 beans.put(((Element) node).getAttribute("id"), initBean(node)); else if (node.getNodeType() == Node.ELEMENT_NODE && node.getNodeName().equals("aop-config")) { // aop配置 initAOP(node); } } } //AOP配置 private void initAOP(Node aopConfig) { for (Node node = aopConfig.getFirstChild(); node != null; node = node .getNextSibling()) { // 为切面节点,配置增强 if (node.getNodeType() == Node.ELEMENT_NODE && node.getNodeName().equals("aspect")) { initAspect(node); } } } //配置AOP切面 private void initAspect(Node aspect) { String aspectRef = ((Element) aspect).getAttribute("ref"); Object adviceBean = null; String expression = ""; Method beforeMethod = null; Method aroundMethod = null; Method afterMethod = null; if (beans.containsKey(aspectRef)) { // 在beans的map中发现已初始化过该bean adviceBean = beans.get(aspectRef); } else { // 未初始化过该bean Node e = dom.getElementById(aspectRef); if (e.getNodeName().equals("bean")) { // 递归调用,初始化被引用的bean adviceBean = initBean(e); } } // 获取切点 // ***************1个切面默认最多只有1个切点、1个前置增强、1个后置增强、1个环绕增强 Node pointcutNode = ParserHelper.getNode(aspect, "pointcut"); expression = ((Element) pointcutNode).getAttribute("expression"); // 获取该切面的增强 for (Node currentNode = aspect.getFirstChild(); currentNode != null; currentNode = currentNode .getNextSibling()) { if (currentNode.getNodeType() != Node.ELEMENT_NODE) continue; // 为相应的增强赋值 String methodName = ((Element) currentNode).getAttribute("method"); try { if (currentNode.getNodeName().equals("before")) { beforeMethod = adviceBean.getClass().getMethod(methodName); } else if (currentNode.getNodeName().equals("around")) { aroundMethod = adviceBean.getClass().getMethod(methodName, ProceedingJoinPoint.class); } else if (currentNode.getNodeName().equals("after")) { afterMethod = adviceBean.getClass().getMethod(methodName); } } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } } // 将该切面交给代理维护 AspectInfo aspectInfo = new AspectInfo(expression, adviceBean, beforeMethod, aroundMethod, afterMethod); ProxyHandler.addAspectInfo(aspectInfo); } //初始化Bean @SuppressWarnings({ "rawtypes", "unchecked" }) private Object initBean(Node node) { // 初始化的类型 Class c = null; // 需要初始化的bean Object object = null; // 生成对象 try { c = Class.forName(((Element) node).getAttribute("class")); object = c.newInstance(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } // 如果此bean为基本类型bean if (isPrimitive(((Element) node).getAttribute("class")) || ((Element) node).hasAttribute("value")) { object = getInstanceForName(((Element) node).getAttribute("class"), ((Element) node).getAttribute("value")); return object; } boolean constructorInit = false;// 是否为构造函数注入 ArrayList
parameterTypes = new ArrayList
(); ArrayList
parameters = new ArrayList(); // 为bean配置属性 for (Node property = node.getFirstChild(); property != null; property = property .getNextSibling()) { if (property.getNodeType() != Node.ELEMENT_NODE) { continue; } if (property.getNodeName().equals("constructor-arg")) { // bean为构造函数注入 constructorInit = true; if (((Element) property).hasAttribute("value")) { // 该参数为基本类型参数 getInstanceForName( ((Element) property).getAttribute("type"), ((Element) property).getAttribute("value")); Class temp = nameToPrimitiveClass(((Element) property) .getAttribute("type")); parameterTypes.add(temp); parameters.add(getInstanceForName( ((Element) property).getAttribute("type"), ((Element) property).getAttribute("value"))); } else if (((Element) property).hasAttribute("ref")) { String refId = ((Element) property).getAttribute("ref"); // 该参数为外部bean引用属性 if (beans.containsKey(refId)) { // 在beans的map中发现已初始化过该bean parameterTypes.add(beans.get(refId).getClass()); parameters.add(beans.get(refId)); } else { // 未初始化过该bean Node e = dom.getElementById(refId); if (e.getNodeName().equals("bean")) { // 递归调用,初始化被引用的bean Class temp = null; try { temp = Class.forName(((Element) e) .getAttribute("class")); } catch (ClassNotFoundException e1) { e1.printStackTrace(); } parameterTypes.add(temp); parameters.add(initBean(e)); } } } } else if (property.getNodeName().equals("property")) { // bean为普通属性注入 String propertyName = ((Element) property).getAttribute("name"); // 获取该属性对应的set方法 Method[] methods = c.getMethods(); Method method = null; for (int k = 0; k < methods.length; k++) { if (methods[k].getName().equalsIgnoreCase( "set" + propertyName)) { method = methods[k]; } } Object value = null;// 属性值 if (((Element) property).hasAttribute("value")) { // 该属性为直接属性,非外部bean引用属性 String propertyValue = ((Element) property) .getAttribute("value"); Class
[] types = method.getParameterTypes(); value = getInstanceForName(types[0].getName(), propertyValue); } else if (((Element) property).hasAttribute("ref")) { String refId = ((Element) property).getAttribute("ref"); // 该属性为外部bean引用属性 if (beans.containsKey(refId)) { // 在beans的map中发现已初始化过该bean value = beans.get(refId); } else { // 未初始化过该bean Node e = dom.getElementById(refId); if (e.getNodeName().equals("bean")) { // 递归调用,初始化被引用的bean value = initBean(e); } } } else if (ParserHelper.containNode(property, "bean")) { // 该属性为内部bean引用属性 Node innerBeanNode = null; for (innerBeanNode = property.getFirstChild(); innerBeanNode != null; innerBeanNode = innerBeanNode .getNextSibling()) { if (innerBeanNode.getNodeName().equals("bean")) { break; } } value = initBean(innerBeanNode); } else if (ParserHelper.containNode(property, "list") || ParserHelper.containNode(property, "set")) { // 属性为list、set集合类型 Collection collection = ParserHelper.containNode( property, "list") ? new ArrayList() : new HashSet(); for (Node currentNode = property.getFirstChild() .getFirstChild(); currentNode != null; currentNode = currentNode .getNextSibling()) { if (currentNode.getNodeName().equals("ref") && (((Element) currentNode) .hasAttribute("bean") && beans .containsKey(((Element) currentNode) .getAttribute("bean")))) { // 该list子元素为引用bean String ref = ((Element) currentNode) .getAttribute("bean"); collection.add(beans.get(ref)); } else if (currentNode.getNodeName().equals("bean")) { // 该list子元素为内部bean collection.add(initBean(currentNode)); } } value = collection; } else if (ParserHelper.containNode(property, "map")) { // 属性为map集合类型 HashMap
map = new HashMap
(); for (Node currentNode = property.getFirstChild() .getFirstChild(); currentNode != null; currentNode = currentNode .getNextSibling()) { if (currentNode.getNodeName().equals("entry") && (((Element) currentNode).hasAttribute("key") && (((Element) currentNode) .hasAttribute("value-ref") && beans .containsKey(((Element) currentNode) .getAttribute("value-ref"))))) { // 该list子元素为引用bean String key = ((Element) currentNode) .getAttribute("key"); String ref = ((Element) currentNode) .getAttribute("value-ref"); map.put(key, beans.get(ref)); } } value = map; } else if (ParserHelper.containNode(property, "props")) { // 属性为props属性类型 Properties props = new Properties(); for (Node currentNode = property.getFirstChild() .getFirstChild(); currentNode != null; currentNode = currentNode .getNextSibling()) { if (currentNode.getNodeName().equals("prop") && ((Element) currentNode).hasAttribute("key")) { // 该list子元素为引用bean String key = ((Element) currentNode) .getAttribute("key"); String propValue = currentNode.getTextContent(); props.setProperty(key, propValue); } } value = props; } // 调用set方法,初始化bean的属性 try { method.invoke(object, value); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } } // 若为构造函数注入 if (constructorInit == true) { Class[] aClasses = {}; Class[] classes = (Class[]) parameterTypes.toArray(aClasses); Object[] prams = (Object[]) parameters.toArray(); try { object = c.getConstructor(classes).newInstance(prams); } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } if (object.getClass().getInterfaces().length == 0) { return object; } else { // 返回经过代理的bean return new ProxyHandler(object).getProxyInstance(); } } // 获取hashMap中相应的bean public Object getBean(String id) { Object bean = beans.get(id); // 未初始化的bean,有可能为懒加载,也有可能没有此bean if (bean == null) { Element element = dom.getElementById(id); if (element.getTagName().equals("bean") && element.hasAttribute("lazy-init") && element.getAttribute("lazy-init").equals("true")) { // 确实为懒加载 // 创建后,存入map中 System.out.println("懒加载:" + id); bean = initBean(element); beans.put(element.getAttribute("id"), bean); } else { // 无此Bean的懒加载声明 System.out.println("找不到此Bean"); } } return bean; } // 检验是否为基本值类型或基本对象 @SuppressWarnings("rawtypes") private boolean isPrimitive(String className) { Class clazz = null; try { clazz = Class.forName(className); } catch (ClassNotFoundException e) { e.printStackTrace(); } String name = clazz.getName(); if (clazz.isPrimitive() || name.equals("java.lang.String") || name.equals("java.lang.Integer") || name.equals("java.lang.Float") || name.equals("java.lang.Double") || name.equals("java.lang.Character") || name.equals("java.lang.Integer") || name.equals("java.lang.Boolean") || name.equals("java.lang.Short")) { return true; } else { return false; } } // 通过字符串反射类型,增加了对基本类型的包装 @SuppressWarnings({ "rawtypes", "unchecked" }) private Object getInstanceForName(String name, String value) { Class clazz = nameToClass(name); Object object = null; try { object = clazz.getConstructor(String.class).newInstance(value); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } return object; } //通过类型名返回基本类型Class(Class.forName()貌似不行) @SuppressWarnings("rawtypes") private Class nameToPrimitiveClass(String name) { Class clazz = null; if (name.equals("int")) { clazz = int.class; } else if (name.equals("char")) { clazz = char.class; } else if (name.equals("boolean")) { clazz = boolean.class; } else if (name.equals("short")) { clazz = short.class; } else if (name.equals("long")) { clazz = long.class; } else if (name.equals("float")) { clazz = float.class; } else if (name.equals("double")) { clazz = double.class; } else if (name.equals("byte")) { clazz = byte.class; } else { try { clazz = Class.forName(name); } catch (ClassNotFoundException e) { e.printStackTrace(); } } return clazz; } //通过类型名获取包装器类 @SuppressWarnings("rawtypes") private Class nameToClass(String name) { Class clazz = null; if (name.equals("int")) { clazz = Integer.class; } else if (name.equals("char")) { clazz = Character.class; } else if (name.equals("boolean")) { clazz = Boolean.class; } else if (name.equals("short")) { clazz = Short.class; } else if (name.equals("long")) { clazz = Long.class; } else if (name.equals("float")) { clazz = Float.class; } else if (name.equals("double")) { clazz = Double.class; } else if (name.equals("byte")) { clazz = Byte.class; } else { try { clazz = Class.forName(name); } catch (ClassNotFoundException e) { e.printStackTrace(); } } return clazz; }}

ParserHelper.java

package cn.seu.bingluo.ioc;import org.w3c.dom.Node;/* * By Bingluo 2012.8.17 * cose.seu.edu.cn * Parser辅助方法 */public class ParserHelper {	//查看Node中是否存在名为name的子节点	public static boolean containNode(Node node,String name){		for (Node currentNode = node.getFirstChild(); currentNode!=null; currentNode = currentNode.getNextSibling()) {			if (currentNode.getNodeName().equals(name)) {				return true;			}		}		return false;	}	//返回名称对应的节点	public static Node getNode(Node node, String name){		for (Node currentNode = node.getFirstChild(); currentNode!=null; currentNode = currentNode.getNextSibling()) {			if (currentNode.getNodeName().equals(name)) {				return currentNode;			}		}		return null;	}}

 

ProxyHandler.java
package cn.seu.bingluo.ioc;import java.lang.reflect.InvocationHandler;/* * 代理类 * 运用jdk动态代理实现,要求前提是被代理对象实现接口 */public class ProxyHandler implements InvocationHandler {	// 存储所有切面	private static HashMap
aspectInfos = new HashMap
(); // 被代理的对象 private Object target = null; public ProxyHandler(Object target) { this.target = target; } public static void addAspectInfo(AspectInfo aspectInfo) { aspectInfos.put(aspectInfo.getExpression(), aspectInfo); } // 获取代理实例 public Object getProxyInstance() { if (target == null) { return null; } return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } // 获取代理实例 public Object getProxyInstance(Object target) { if (target == null) { return null; } this.target = target; return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { ArrayList
aspects = new ArrayList
(); Set
> entrySet = aspectInfos.entrySet(); Object result = null; //遍历切面列表,找到对应的切面 for (Entry
entry : entrySet) { AspectInfo aspectInfo = entry.getValue(); Object adviceBean = aspectInfo.getAdviceBean(); String expression = aspectInfo.getExpression(); Pattern pattern = Pattern.compile(expression); Matcher matcher = pattern.matcher(target.getClass().getName() + "." + method.getName()); if (matcher.find()) { AspectInfo aspect = new AspectInfo(); aspect.setAdviceBean(adviceBean); aspect.setBeforeMethod(aspectInfo.getBeforeMethod()); aspect.setAroundMethod(aspectInfo.getAroundMethod()); aspect.setAfterMethod(aspectInfo.getAfterMethod()); aspects.add(aspect); } } // 执行before增强 for (AspectInfo aspect : aspects) { Object adviceBean = aspect.getAdviceBean(); if (aspect.getBeforeMethod() != null) { aspect.getBeforeMethod().invoke(adviceBean, new Object[]{}); } } // 执行around增强 Object aroundAdviceBean = target; Method aroundAdviceMethod = method; Object[] aroundAdviceArgs = args; for (AspectInfo aspect : aspects) { Object adviceBean = aspect.getAdviceBean(); if (aspect.getAroundMethod() != null) { aroundAdviceArgs = new Object[] { new ProceedingJoinPoint( aroundAdviceBean, aroundAdviceMethod, aroundAdviceArgs) }; aroundAdviceBean = adviceBean; aroundAdviceMethod = aspect.getAroundMethod(); } } result = aroundAdviceMethod.invoke(aroundAdviceBean, aroundAdviceArgs); // 执行After增强 for (AspectInfo aspect : aspects) { Object adviceBean = aspect.getAdviceBean(); if (aspect.getAfterMethod() != null) { aspect.getAfterMethod().invoke(adviceBean, new Object[]{}); } } return result; }}

 

ProceedingJoinPoint.java

package cn.seu.bingluo.ioc;import java.lang.reflect.InvocationTargetException;/* * 用于处理AOP代理链时,封装相关信息作为统一参数进行传递 */public class ProceedingJoinPoint {	private Object object;//被代理的对象	private Method method;//被代理的方法	private Object[] args;//方法相应的参数	public ProceedingJoinPoint(Object object, Method method, Object[] args){		this.object = object;		this.method = method;		this.args = args;	}	//执行目标函数	public Object excute(){		Object result = null;		try {			result = method.invoke(object, args);		} catch (IllegalArgumentException e) {			e.printStackTrace();		} catch (IllegalAccessException e) {			e.printStackTrace();		} catch (InvocationTargetException e) {			e.printStackTrace();		}		return result;	}}
 

AspectInfo.java

package cn.seu.bingluo.ioc;import java.lang.reflect.Method;/* * 切面信息Bean * 每1个切面最多只有: * 1个切点expression * 1个增强bean * 1个前置增强、环绕增强、后置增强 */public class AspectInfo {	private String expression = "";	private Object adviceBean = null;	private Method beforeMethod = null;	private Method aroundMethod = null;	private Method afterMethod = null;	public AspectInfo(){	}	public AspectInfo(String expression, Object adviceBean,			Method beforeMethod, Method aroundMethod, Method afterMethod) {		setExpression(expression);		setAdviceBean(adviceBean);		setBeforeMethod(beforeMethod);		setAroundMethod(aroundMethod);		setAfterMethod(afterMethod);	}	public String getExpression() {		return expression;	}	public void setExpression(String expression) {		this.expression = expression;	}	public Object getAdviceBean() {		return adviceBean;	}	public void setAdviceBean(Object adviceBean) {		this.adviceBean = adviceBean;	}	public Method getBeforeMethod() {		return beforeMethod;	}	public void setBeforeMethod(Method beforeMethod) {		this.beforeMethod = beforeMethod;	}	public Method getAroundMethod() {		return aroundMethod;	}	public void setAroundMethod(Method aroundMethod) {		this.aroundMethod = aroundMethod;	}	public Method getAfterMethod() {		return afterMethod;	}	public void setAfterMethod(Method afterMethod) {		this.afterMethod = afterMethod;	}}

autumn.dtd

接下来,我们来测试一下框架功能是否实现!

先测试IOC,测试bean的装配,写个POJO类

TestIOCBean.java

package cn.seu.bingluo.ioc;import java.util.Collection;/* * By Bingluo 2012.8.17 * cose.seu.edu.cn * 测试Bean */public class TestIOCBean {	private int a;	private Integer aa;	private String b;	private TestIOCBean innerBean;	private TestIOCBean outterBean;	private Collection
collection; private Map
map; private Properties props; public TestIOCBean(){ } public TestIOCBean(int a,String b,TestIOCBean oBeanTest) { this.setA(a); this.setB(b); this.setOutterBean(oBeanTest); } public Integer getA() { return a; } public void setA(int a){ this.a = a; } public Integer getAa() { return aa; } public void setAa(Integer aa) { this.aa = aa; } public String getB() { return b; } public void setB(String b) { this.b = b; } public TestIOCBean getInnerBean() { return innerBean; } public void setInnerBean(TestIOCBean innerBean) { this.innerBean = innerBean; } public TestIOCBean getOutterBean() { return outterBean; } public void setOutterBean(TestIOCBean outterBean) { this.outterBean = outterBean; } public Collection
getCollection() { return collection; } public void setCollection(Collection
collection) { this.collection = collection; } public Map
getMap() { return map; } public void setMap(Map
map) { this.map = map; } public Properties getProps() { return props; } public void setProps(Properties props) { this.props = props; }}

再写一个Service类,用于测试AOP功能,注意,框架AOP功能是用JDK动态代理实现的,故必须继承自某个接口:

ITestAOPBean.java

package cn.seu.bingluo.ioc;/* * 必须被继承才能实现AOP代理 */public interface ITestAOPBean {	public int shout();}

TestAOPBean.java

package cn.seu.bingluo.ioc;/* * 测试AOP功能 * 用jdk动态代理实现,故必须继承接口 */public class TestAOPBean implements ITestAOPBean{	private String name = "aop-test";	public String getName() {		return name;	}	public void setName(String name) {		this.name = name;	}	@Override	public int shout() {		System.out.println("Hello, My name is "+name);		return 1;	}}

再为这个service写一个增强类,将该类中的方法织入service的shout()中。

Advice.java

package cn.seu.bingluo.ioc;/* * 增强类 * 用于测试AOP功能 */public class Advice {	public void Before(){		System.out.println("Before...");	}	public Object Around(ProceedingJoinPoint joinPoint){		System.out.println("Before-around...");		Object object = joinPoint.excute();		System.out.println("After-around...");		return object;	}	public void After(){		System.out.println("After...");	}}

到这里,重点来了,我们就需要将bean配置起来了,建立xml文件:

config.xml(注意用dtd约束)

im' props' value: s3
im' props' value: s4

最后,再写一个main函数驱动一下,就大功告成啦!

Driver.java

package cn.seu.bingluo.ioc;import java.util.Iterator;public class Driver {	/**	 * @param args	 */	@SuppressWarnings("rawtypes")	public static void main(String[] args) {		// 测试桩		// 解析IOC配置文件		ConfigManager configManager = new ConfigManager("config.xml");		// 获取id为“bean”的Bean		TestIOCBean beanTest = (TestIOCBean) configManager.getBean("bean");		System.out.println(beanTest.getA() + ":" + beanTest.getAa() + ":"				+ beanTest.getB());		System.out.println(beanTest.getInnerBean().getB());		System.out.println(beanTest.getInnerBean().getOutterBean().getB());		String string = (String) configManager.getBean("str1");		System.out.println(string);		string = (String) configManager.getBean("str2");		System.out.println(string);		// 装配集合测试		List
list = (List
) beanTest.getCollection(); System.out.println(list.get(0)); Set
set = (Set
) beanTest.getInnerBean().getCollection(); for (Iterator it = set.iterator(); it.hasNext();) { System.out.println("value=" + it.next().toString()); } TestIOCBean outterBeanTest = (TestIOCBean) configManager .getBean("outterBean"); System.out.println(outterBeanTest.getMap().get("s1")); System.out.println(outterBeanTest.getProps().get("s3")); //测试构造函数注入 TestIOCBean constructorBeanTest = (TestIOCBean) configManager .getBean("constructorInit"); System.out.println(constructorBeanTest.getA() + constructorBeanTest.getB() + constructorBeanTest.getOutterBean().getAa()); //测试AOP功能 System.out.println("\n***************** AOP测试 *****************"); ITestAOPBean testBean = (ITestAOPBean) configManager.getBean("shoutBean"); testBean.shout(); }}

运行结果:

 

功能算是实现啦!

如果有发现什么问题或者不足的话,欢迎给我留言或者发送邮件。谢谢!

邮箱:bingluo#foxmail.com(#转为@)

转载于:https://my.oschina.net/cose/blog/73919

你可能感兴趣的文章
ASP.NET视频教程 手把手教你做企业论坛网站 视频教程
查看>>
[LeetCode] Meeting Rooms II
查看>>
从Swift学习iOS开发的路线指引
查看>>
3.1链表----链表(Linked List)入门
查看>>
[布局] bootstrap基本标签总结
查看>>
异步编程思想
查看>>
"数学口袋精灵"bug(团队)
查看>>
2017python第六天作业 面向对象 本节作业: 选课系统
查看>>
【找规律】Divide by Zero 2017 and Codeforces Round #399 (Div. 1 + Div. 2, combined) B. Code For 1...
查看>>
Scribes:小型文本编辑器,支持远程编辑
查看>>
为什么要使用 SPL中的 SplQueue实现队列
查看>>
文件的相关操作(创建、打开、写入、读出、重命名)
查看>>
品尝阿里云容器服务:用nginx镜像创建容器,体验基于域名的路由机制
查看>>
PHP const关键字
查看>>
ssh 安装笔记
查看>>
游戏音效下载网站大全
查看>>
angular $resouse服务
查看>>
实验五
查看>>
文法分析
查看>>
记那次失败了的面试
查看>>