SSH框架之Spring
来源:互联网 发布:coc国王升级数据 编辑:程序博客网 时间:2024/05/01 19:37
概述
- 核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开
- Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
- Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。
- Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
- Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
- Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
- Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。
控制反转(IOC)
IOC是Inversion of Control
IOC理解
1、未使用IOC,软件系统中紧耦合的对象
2、IOC解耦过程
IOC理论提出的观点大体是这样的:借助于“第三方”实现具有依赖关系的对象之间的解耦
由于引进了中间位置的“第三方”,也就是IOC容器,使得A、B、C、D这4个对象没有了耦合关系
IOC容器成了整个系统的关键核心,它起到了一种类似“粘合剂”的作用,把系统中的所有对象粘合在一起发挥作用
3、拿掉IoC容器后的系统
控制反转(IOC)到底为什么要起这么个名字?
软件系统在没有引入IOC容器之前,如图1所示,对象A依赖于对象B,那么对象A在初始化或者运行到某一点的时候,自己必须主动去创建对象B或者使用已经创建的对象B。无论是创建还是使用对象B,控制权都在自己手上。
软件系统在引入IOC容器之后,这种情形就完全改变了,如图3所示,由于IOC容器的加入,对象A与对象B之间失去了直接联系,所以,当对象A运行到需要对象B的时候,IOC容器会主动创建一个对象B注入到对象A需要的地方。
通过前后的对比,我们不难看出来:对象A获得依赖对象B的过程,由主动行为变为了被动行为,控制权颠倒过来了,这就是“控制反转”这个名称的由来。
依赖注入(DI)
既然IOC是控制反转,那么到底是“哪些方面的控制被反转了呢?”,经过详细地分析和论证后,他得出了答案:“获得依赖对象的过程被反转了”。控制被反转之后,获得依赖对象的过程由自身管理变为了由IOC容器主动注入。于是,他给“控制反转”取了一个更合适的名字叫做“依赖注入(Dependency Injection)”。他的这个答案,实际上给出了实现IOC的方法:注入。所谓依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。
所以,依赖注入(DI)和控制反转(IOC)是从不同的角度的描述的同一件事情,就是指通过引入IOC容器,利用依赖关系注入的方式,实现对象之间的解耦。
对象A依赖于对象B,当对象 A需要用到对象B的时候,IOC容器就会立即创建一个对象B送给对象A。IOC容器就是一个对象制造工厂,你需要什么,它会给你送去,你直接使用就行了,而再也不用去关心你所用的东西是如何制成的,也不用关心最后是怎么被销毁的,这一切全部由IOC容器包办。
在传统的实现中,由程序内部代码来控制组件之间的关系。我们经常使用new关键字来实现两个组件之间关系的组合,这种实现方式会造成组件之间耦合。IOC很好地解决了该问题,它将实现组件间关系从程序内部提到外部容器,也就是说由容器在运行期将组件间的某种依赖关系动态注入组件中。
IOC实现原理
IOC中最基本的技术就是“反射(Reflection)”编程
有关反射的概念和用法,大家应该都很清楚,通俗来讲就是根据给出的类名(字符串方式)来动态地生成对象
我们可以把IOC容器的工作模式看做是工厂模式的升华,可以把IOC容器看作是一个工厂,这个工厂里要生产的对象都在配置文件中给出定义,然后利用编程语言的的反射编程,根据配置文件中给出的类名生成相应的对象。从实现来看,IOC是把以前在工厂方法里写死的对象生成代码,改变为由配置文件来定义,也就是把工厂和对象生成这两者独立分隔开来,目的就是提高灵活性和可维护性。
使用IOC框架应该注意什么
- 第一、软件系统中由于引入了第三方IOC容器,生成对象的步骤变得有些复杂,本来是两者之间的事情,又凭空多出一道手续,所以,我们在刚开始使用IOC框架的时候,会感觉系统变得不太直观。
- 第二、由于IOC容器生成对象是通过反射方式,在运行效率上有一定的损耗。如果你要追求运行效率的话,就必须对此进行权衡。
- 第三、具体到IOC框架产品(比如:Spring)来讲,需要进行大量的配制工作,比较繁琐,对于一些小的项目而言,客观上也可能加大一些工作成本。
自定义Spring实现
首先,我们定义一个Bean类,这个类用来存放一个Bean拥有的属性
/* Bean Id */ private String id; /* Bean Class */ private String type; /* Bean Property */ private Map<String, Object> properties = new HashMap<String, Object>();
一个Bean包括id,type,和Properties。
接下来Spring 就开始加载我们的配置文件了,将我们配置的信息保存在一个HashMap中,HashMap的key就是Bean 的 Id ,HasMap 的value是这个Bean
<bean id="test" class="Test"> <property name="testMap"> <map> <entry key="a"> <value>1</value> </entry> <entry key="b"> <value>2</value> </entry> </map> </property> </bean>
Spring是怎样保存上面的配置呢?,代码如下:
if (beanProperty.element("map") != null) { Map<String, Object> propertiesMap = new HashMap<String, Object>(); Element propertiesListMap = (Element) beanProperty .elements().get(0); Iterator<?> propertiesIterator = propertiesListMap .elements().iterator(); while (propertiesIterator.hasNext()) { Element vet = (Element) propertiesIterator.next(); if (vet.getName().equals("entry")) { String key = vet.attributeValue("key"); Iterator<?> valuesIterator = vet.elements() .iterator(); while (valuesIterator.hasNext()) { Element value = (Element) valuesIterator.next(); if (value.getName().equals("value")) { propertiesMap.put(key, value.getText()); } if (value.getName().equals("ref")) { propertiesMap.put(key, new String[] { value .attributeValue("bean") }); } } } } bean.getProperties().put(name, propertiesMap); }
接下来就进入最核心部分了,让我们看看Spring 到底是怎么依赖注入的吧,其实依赖注入的思想也很简单,它是通过反射机制实现的,在实例化一个类时,它通过反射调用类中set方法将事先保存在HashMap中的类属性注入到类中。让我们看看具体它是怎么做的吧。
首先实例化一个类,像这样
public static Object newInstance(String className) { Class<?> cls = null; Object obj = null; try { cls = Class.forName(className); obj = cls.newInstance(); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } catch (InstantiationException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } return obj; }
接着它将这个类的依赖注入进去,像这样
public static void setProperty(Object obj, String name, String value) { Class<? extends Object> clazz = obj.getClass(); try { String methodName = returnSetMthodName(name); Method[] ms = clazz.getMethods(); for (Method m : ms) { if (m.getName().equals(methodName)) { if (m.getParameterTypes().length == 1) { Class<?> clazzParameterType = m.getParameterTypes()[0]; setFieldValue(clazzParameterType.getName(), value, m, obj); break; } } } } catch (SecurityException e) { throw new RuntimeException(e); } catch (IllegalArgumentException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); } }
最后它将这个类的实例返回给我们,我们就可以用了。我们还是以Map为例看看它是怎么做的,我写的代码里面是创建一个HashMap并把该HashMap注入到需要注入的类中,像这样
if (value instanceof Map) { Iterator<?> entryIterator = ((Map<?, ?>) value).entrySet() .iterator(); Map<String, Object> map = new HashMap<String, Object>(); while (entryIterator.hasNext()) { Entry<?, ?> entryMap = (Entry<?, ?>) entryIterator.next(); if (entryMap.getValue() instanceof String[]) { map.put((String) entryMap.getKey(), getBean(((String[]) entryMap.getValue())[0])); } } BeanProcesser.setProperty(obj, property, map); }
Spring实际应用配置文件
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"><beans><bean id="createCreditCard" -->define createCreditCard definitionclass="springexample.creditcardaccount.CreateCreditCardAccount"><property name="creditRatingInterface">-->inject creditRatingInterface dependency via creditRating reference bean(依赖注入)<ref bean="creditRating" /></property><property name="creditLinkingInterface">">-->inject creditLinkingInterface dependency via creditLinking reference bean(依赖注入)<ref bean="creditLinking" /></property><property name="emailInterface">">">-->inject emailInterface dependency via email reference bean<ref bean="email" />/property></bean><bean id="creditLinking" class="springexample.creditlinking.CreditLinking"><property name="url"><value>http://localhost/creditLinkService</value>-->set url property value (赋值)</property></bean><bean id="creditRating" class="springexample.creditrating.CreditRating"></bean><bean id="email" class="springexample.email.Email"><property name="smtpHost"><value>localhost</value>>-->set smpHtpHost property value </property><property name="fromEmail"><value>mycompanyadmin@mycompanyadmin.com</value></property><property name="userId"><value>myuserid</value></property><property name="password"><value>mypassword</value></property></bean></beans>
Spring AOP
AOP(Aspect Orient Programming),也就是面向方面编程,作为面向对象编程的一种补充,专门用于处理系统中分布于各个模块(不同方法)中的交叉关注点的问题,在 Java EE 应用中,常常通过 AOP 来处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、对象池管理等。AOP 实现的关键就在于 AOP 框架自动创建的 AOP 代理,AOP 代理主要分为静态代理和动态代理两大类,静态代理以 AspectJ 为代表;而动态代理则以 Spring AOP 为代表。
其中静态代理是指使用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因此也称为编译时增强;而动态代理则在运行时借助于 JDK 动态代理、CGLIB 等在内存中“临时”生成 AOP 动态代理类,因此也被称为运行时增强。
AOP存在的价值
现在假设系统中有 3 段完全相似的代码,这些代码通常会采用“复制”、“粘贴”方式来完成,通过这种“复制”、“粘贴”方式开发出来的软件如图 1 所示。
图 1.多个地方包含相同代码的软件
看到如图 1 所示的示意图,可能有的读者已经发现了这种做法的不足之处:如果有一天,图 1 中的深色代码段需要修改,那是不是要打开 3 个地方的代码进行修改?如果不是 3 个地方包含这段代码,而是 100 个地方,甚至是 1000 个地方包含这段代码段,那会是什么后果?
为了解决这个问题,我们通常会采用将如图 1 所示的深色代码部分定义成一个方法,然后在 3 个代码段中分别调用该方法即可。在这种方式下,软件系统的结构如图 2 所示。
图 2 通过方法调用实现系统功能
对于如图 2 所示的软件系统,如果需要修改深色部分的代码,只要修改一个地方即可,不管整个系统中有多少地方调用了该方法,程序无须修改这些地方,只需修改被调用的方法即可——通过这种方式,大大降低了软件后期维护的复杂度。
对于如图 2 所示的方法 1、方法 2、方法 3 依然需要显式调用深色方法,这样做能够解决大部分应用场景。但对于一些更特殊的情况:应用需要方法 1、方法 2、方法 3 彻底与深色方法分离——方法 1、方法 2、方法 3 无须直接调用深色方法,那如何解决?
因为软件系统需求变更是很频繁的事情,系统前期设计方法 1、方法 2、方法 3 时只实现了核心业务功能,过了一段时间,我们需要为方法 1、方法 2、方法 3 都增加事务控制;又过了一段时间,客户提出方法 1、方法 2、方法 3 需要进行用户合法性验证,只有合法的用户才能执行这些方法;又过了一段时间,客户又提出方法 1、方法 2、方法 3 应该增加日志记录;又过了一段时间,客户又提出……面对这样的情况,我们怎么办?通常有两种做法:
- 根据需求说明书,直接拒绝客户要求。
- 拥抱需求,满足客户的需求。
第一种做法显然不好,客户是上帝,我们应该尽量满足客户的需求。通常会采用第二种做法,那如何解决呢?是不是每次先定义一个新方法,然后修改方法 1、方法 2、方法 3,增加调用新方法?这样做的工作量也不小啊!我们希望有一种特殊的方法:我们只要定义该方法,无须在方法 1、方法 2、方法 3 中显式调用它,系统会“自动”执行该特殊方法。
上面想法听起来很神奇,甚至有一些不切实际,但其实是完全可以实现的,实现这个需求的技术就是 AOP。AOP 专门用于处理系统中分布于各个模块(不同方法)中的交叉关注点的问题,在 Java EE 应用中,常常通过 AOP 来处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、对象池管理等,AOP 已经成为一种非常常用的解决方案。
基本概念
- 切面(Aspect)
官方的抽象定义为“一个关注点的模块化,这个关注点可能会横切多个对象”,“切面”在ApplicationContext中< aop:aspect >来配置。 - 连接点(Joinpoint)
程序执行过程中的某一行为。 - 通知(Advice)
“切面”对于某个“连接点”所产生的动作,一个“切面”可以包含多个“Advice”。Advice共有如下5种类型:
A. 前置通知(Before advice) :在某连接点(JoinPoint)之前执行的通知,但这个通知不能阻止连接点前的执行。xml中在< aop:aspect>里面使用< aop:before>元素进行声明;
B 后通知(After advice) :当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。xml中在< aop:aspect>里面使用< aop:after>元素进行声明
C 返回后通知(After return advice) :在某连接点正常完成后执行的通知,不包括抛出异常的情况。xml中在< aop:aspect>里面使用< after-returning>元素进行声明。
D 环绕通知(Around advice) :包围一个连接点的通知,类似Web中Servlet规范中的Filter的doFilter方法。可以在方法的调用前后完成自定义的行为,也可以选择不执行。xml中在< aop:aspect>里面使用< aop:around>元素进行声明。例如,TestAspect中的doAround方法。
E 抛出异常后通知(After throwing advice) : 在方法抛出异常退出时执行的通知。xml中在< aop:aspect>里面使用< aop:after-throwing>元素进行声明。
通知执行顺序:前置通知→环绕通知连接点之前→连接点执行→环绕通知连接点之后→返回通知→后通知 →(如果发生异常)异常通知→后通知
匹配语法
- * 匹配任何数量字符;
- .. 匹配任何数量字符的重复,如在类型模式中匹配任何数量子包;而在方法参数模式中匹配任何数量参数。
- +匹配指定类型的子类型;仅能作为后缀放在类型模式后边。
常用的匹配种类
1. 类
注解 类名
注解:可选,类上持有的注解,如@Deprecated;
类名:必填,任何类的完整名称
2 方法
注解 修饰符 返回值类型 类名 方法名(参数列表) 异常列表
注解:可选,方法上持有的注解,如@Deprecated;
修饰符:可选,如public、protected;
返回值类型:必填,可以是任何类型模式;“*”表示所有类型;
类名:可选,任何类的完整名称;
方法名:必填,可以使用“*”进行模式匹配;
参数列表:“()”表示方法没有任何参数;“(..)”表示匹配接受任意个参数的方法,“(..,java.lang.String)”表示匹配接受java.lang.String类型的参数结束,且其前边可以接受有任意个参数的方法;“(java.lang.String,..)” 表示匹配接受java.lang.String类型的参数开始,且其后边可以接受任意个参数的方法;“(*,java.lang.String)” 表示匹配接受java.lang.String类型的参数结束,且其前边接受有一个任意类型参数的方法;
异常列表:可选,以“throws 异常全限定名列表”声明,异常全限定名列表如有多个以“,”分割,如throws java.lang.IllegalArgumentException, java.lang.ArrayIndexOutOfBoundsException。
参考:
http://blog.csdn.net/wangpeng047/article/details/8556800
AOP日志实现实例
在java开发中日志的管理有很多种。我一般会使用过滤器,或者是Spring的拦截器进行日志的处理。如果是用过滤器比较简单,只要对所有的.do提交进行拦截,然后获取action的提交路径就可以获取对每个方法的调用。然后进行日志记录。使用过滤器的好处是可以自己选择性的对某一些方法进行过滤,记录日志。但是实现起来有点麻烦。
另外一种就是使用Spring的AOP了。这种方式实现起来非常简单,只要配置一下配置文件就可以了。可是这种方式会拦截下所有的对action的每个操作。使得效率比较低。不过想做详细日志这个方法还是非常好的。下面我就介绍一下使用Spring AOP进行日志记录的方式。
第一种。Spring AOP对普通类的拦截操作
首先我们要写一个普通类,此类作为日志记录类。 比如
package chen.hui.log public classs MyLog{ //在类里面写方法,方法名诗可以任意的。此处我用标准的before和after来表示 public void before(){ System.out.println("被拦截方法调用之前调用此方法,输出此语句"); } public void after(){ System.out.println("被拦截方法调用之后调用此方法,输出此语句"); } } 其次我们在写一个类作为被拦截类(Spring的AOP就是拦截这个类里面的方法) package chen.hui.log public class Test{//此类中方法可以写任意多个。我只写一个 public void test(){ Sytem.out.println("测试类的test方法被调用"); } }
最后进行配置文件的编写。在Spring的配置文件中我们需要进行几句话的配置
<bean id="testLog" class="chen.hui.log.MyLog"></bean> <!--将日志类注入到bean中。--> <aop:config> <aop:aspect id="b" ref="testLog"><!--调用日志类--> <aop:pointcut id="log" expression="execution(* chen.hui.log.*.*(..))"/><!--配置在log包下所有的类在调用之前都会被拦截--> <aop:before pointcut-ref="log" method="before"/><!--在log包下面所有的类的所有方法被调用之前都调用MyLog中的before方法--> <aop:after pointcut-ref="log" method="after"/>><!--在log包下面所有的类的所有方法被调用之前都调用MyLog中的after方法--> </aop:aspect> </aop:config>
到此处整个程序完成,在MyLog类里面的before和after方法添加日志逻辑代码就可以完成日志的管理。以上是对普通类的管理,如果只想拦截某一个类。只要把倒数第二个 * 改成类名就可以了。
第二:使用Spring AOP对action做日志管理
如果是想拦截action对action做日志管理,基本和上面差不多,但是要注意。以下几点
首先还是要写一个普通类,不过此类中的方法需要传入参数。 比如
package chen.hui.log import org.aspectj.lang.JoinPoint; public classs MyLog{ //在类里面写方法,方法名诗可以任意的。此处我用标准的before和after来表示 //此处的JoinPoint类可以获取,action所有的相关配置信息和request等内置对象。 public void before(JoinPoint joinpoint){ joinpoint.getArgs();//此方法返回的是一个数组,数组中包括request以及ActionCofig等类对象 System.out.println("被拦截方法调用之前调用此方法,输出此语句"); } public void after(JoinPoint joinpoint){ System.out.println("被拦截方法调用之后调用此方法,输出此语句"); } }
其次我们在写一个action类作为被拦截类(Spring的AOP就是拦截这个类里面的方法)
package chen.hui.log public class LoginAction{//此类中方法可以写任意多个。我只写一个 public void test(){ Sytem.out.println("测试类的test方法被调用"); } }
最后进行配置文件的编写。在Spring的配置文件中我们需要进行几句话的配置
<bean id="testLog" class="chen.hui.log.MyLog"></bean> <!--将日志类注入到bean中。--> <aop:config> <aop:aspect id="b" ref="testLog"><!--调用日志类--> <aop:pointcut id="log" expression="execution(* chen.hui.log.*.*(..))"/><!--配置在log包下所有的类在调用之前都会被拦截--> <aop:before pointcut-ref="log" method="before"/><!--在log包下面所有的类的所有方法被调用之前都调用MyLog中的before方法--> <aop:after pointcut-ref="log" method="after"/>><!--在log包下面所有的类的所有方法被调用之前都调用MyLog中的after方法--> </aop:aspect> </aop:config>
除了参数外其他地方基本和普通类相似。
需要注意的是:普通类可以监控单一的类,而action在配置文件中只能到包名而不能到action的类名。不然会报错。就是说如果要记录日志就要记录所有的action而不能记录其中一个,这是我试了好久得出的结果。
.实现登陆和日志管理(使用Spring AOP)
- LoginService LogService TestMain
- 用Spring 管理 LoginService 和 LogService 的对象
- 确定哪些连接点是切入点,在配置文件中
- 将LogService封装为通知
- 将通知植入到切入点
<aop:config> <aop:pointcut expression="execution(* cn.com.spring.service.impl.*.*(..))" id="myPointcut"/> <!--将哪个--> <aop:aspect id="dd" ref="logService"> <aop:before method="log" pointcut-ref="myPointcut"/> </aop:aspect></aop:config>
execution(* * cn.com.spring.service.impl..(..))
- *所有的修饰符
- *所有的返回类型
- *所有的类名
- *所有的方法名
- ..所有的参数名
1.ILoginService.java
package cn.com.spring.service;public interface ILoginService { public boolean login(String userName, String password);}
2.LoginServiceImpl.java
package cn.com.spring.service.impl;import cn.com.spring.service.ILoginService;public class LoginServiceImpl implements ILoginService { public boolean login(String userName, String password) { System.out.println("login:" + userName + "," + password); return true; }}
3.ILogService.java
package cn.com.spring.service;import org.aspectj.lang.JoinPoint;public interface ILogService { //无参的日志方法 public void log(); //有参的日志方法 public void logArg(JoinPoint point); //有参有返回值的方法 public void logArgAndReturn(JoinPoint point,Object returnObj);}
4.LogServiceImpl.java
package cn.com.spring.service.impl;import org.aspectj.lang.JoinPoint;import cn.com.spring.service.ILogService;public class LogServiceImpl implements ILogService { @Override public void log() { System.out.println("*************Log*******************"); } //有参无返回值的方法 public void logArg(JoinPoint point) { //此方法返回的是一个数组,数组中包括request以及ActionCofig等类对象 Object[] args = point.getArgs(); System.out.println("目标参数列表:"); if (args != null) { for (Object obj : args) { System.out.println(obj + ","); } System.out.println(); } } //有参并有返回值的方法 public void logArgAndReturn(JoinPoint point, Object returnObj) { //此方法返回的是一个数组,数组中包括request以及ActionCofig等类对象 Object[] args = point.getArgs(); System.out.println("目标参数列表:"); if (args != null) { for (Object obj : args) { System.out.println(obj + ","); } System.out.println(); System.out.println("执行结果是:" + returnObj); } }}
5.applicationContext.java
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <bean id="logService" class="cn.com.spring.service.impl.LogServiceImpl"></bean> <bean id="loginService" class="cn.com.spring.service.impl.LoginServiceImpl"></bean> <aop:config> <!-- 切入点 --> <aop:pointcut expression="execution(* cn.com.spring.service.impl.LoginServiceImpl.*(..))" id="myPointcut" /> <!-- 切面: 将哪个对象中的哪个方法,织入到哪个切入点 --> <aop:aspect id="dd" ref="logService"> <!-- 前置通知 <aop:before method="log" pointcut-ref="myPointcut" /> <aop:after method="logArg" pointcut-ref="myPointcut"> --> <aop:after-returning method="logArgAndReturn" returning="returnObj" pointcut-ref="myPointcut"/> </aop:aspect> </aop:config></beans>
6.TestMain.java
public class TestMain {public static void testSpringAOP(){ ApplicationContext ctx = new ClassPathXmlApplicationContext("app*.xml"); ILoginService loginService = (ILoginService)ctx.getBean("loginService"); loginService.login("zhangsan", "12344");}public static void main(String[] args) {testSpringAOP();}}
7.输出结果:
login:zhangsan,12344
目标参数列表:
zhangsan,
12344,
执行结果是:true
解析:
1.先调用了login()方法System.out.println(“login:” + userName + “,” + password);
2.再调用了logArgAndReturn()方法输出了日志,并且返回了login()方法是否成功
System.out.println("目标参数列表:"); if (args != null) { for (Object obj : args) { System.out.println(obj + ","); } System.out.println(); System.out.println("执行结果是:" + returnObj); }
- SSH 框架之Spring
- SSH框架之Spring
- SSH之 spring框架配置文件
- SSH:Spring框架(spring之AOP)
- SSH框架构造之三---------------spring 注入
- 万能框架spring(三)之SSH
- SSH三大框架初探之Spring
- SSH框架入门学习之二(spring)
- SSH框架之Spring的代理模式
- ssh框架整合之spring整合
- spring框架,ssh框架
- SSH框架搭建过程---之Spring框架的使用(2)
- SSH框架搭建过程---之Struts整合Spring框架(4)
- SSH框架-Spring
- SSH框架中的Spring
- 【SSH】Spring框架学习
- SSH框架(spring)
- 《SSH框架》---spring
- 大牛畅谈“技术成长的烦恼”:大家都能做,说明你做的还不够好
- 登录
- MyEclipse+Git使用详解
- 对之前Android基础的一些整理(一)
- 封装caffe-windows-master为动态链接库
- SSH框架之Spring
- Hybrid App学习心得:cordova + ionic + angularjs
- awk命令
- LaTeX练习
- windows编程之线程操作
- imageView
- android app瘦身
- 在mysql Navicat中怎样设置ID自动递增
- BZOJ 4197: [Noi2015]寿司晚宴 DP