1.经过PropertyPlaceholderConfigurer在Spring中加载其余外部配置文件或者属性文件:html
在不少javaEE工程中,Spring的角色很是重要,是一个管理其余模块和组件的轻量级容器,Spring常常须要管理Struts、Ibatis、Hibernate等,这些开源框架的配置文件就经过Spring的PropertyPlaceholderConfigurer加载在Spring中进行管理,另外,数据库链接信息、JNDI链接信息属性文件等也能够经过PropertyPlaceholderConfigurer加载到Spring中来管理。用法以下:java
(1).经过PropertyPlaceholderConfigurer将其余文件加载到Spring中:node
在spring配置文件中添加以下配置:web
[xhtml] view plain copy print?spring
<bean class=“org.springframework.beans.factory.config.PropertyPlaceholderConfigurer“> <property name=“locations“> <value>classpath:要加载的文件名</value> …… </property> </bean> 数据库
(2).通过(1)中的配置要加载的配置或属性文件就被加载到spring中,若是还须要在运行时使用加载进来的配置或数据文件的一些信息,如使用数据库链接信息或者JNDI链接信息时,就可使用类型EL表达式的语法进行引用,例如:express
[xhtml] view plain copy print?apache
<bean id=”dataSource” destroy-method=”close” class=”org.apache.common.dbcp.BasicDataSource”> <!--假设数据库链接信息写在外部属性文件中,已经被spring加载--> <property name=”driverClassName” value=”${driver}”/> <property name=”url” value=”${url}”/> <property name=”username” value=”${username}”/> <property name=”password” value=”${password}”/> </bean> 编程
注意:也可使用<context:Property-Placeholderlocation=”classpath:要加载的文件名”/>设计模式
2.Java的动态代理:
Spring的面向切面编程(AOP)底层实现原理是动态代理,所以在学习面向切面编程以前必须先了解动态代理。
Java中动态代理应用很是普遍,动态代理是23中设计模式中很是经常使用的经典设计模式之一。动态代理的原理是,当要调用一个目标对象或者其方法时,系统并非直接返回目标对象,而是返回一个代理对象,经过这个代理对象去访问目标对象或者目标对象的方法。
动态代理的简单原理以下:
客户端调用者——>代理对象——>被调用的目标对象。
当客户端调用代理对象时,代理对象委派目标对象调用其业务方法。
动态代理分为两种,针对接口的动态代理和针对普通类的动态代理,java中的动态代理是真的接口的动态代理,cglib是针对普通类的动态代理,目标javaEE的依赖包和Spring的jar包中已经包含了cglib相关jar包,所以便可以对代理也能够对普通类进行动态代理。
(1).java的针对接口动态代理:
Java中的动态代理只能针对接口进行动态代理,所以,目标对象必须实现接口,代理对象要实现目标对象的全部接口。工做流程以下:
a. 动态代理类编写:
注意:动态代理必须实现InvocationHandler接口,同时实现如下方法:
[java] view plain copy print?
Object invoke(Objectm代理实例,Method代理实例上调用的接口方法的Method 实例,Object[] 传入代理实例上方法调用的参数值的对象数组);
安装JDK的文档说明,该方法做用是传递代理实例、识别调用方法的 java.lang.reflect.Method
对象以及包含参数的 Object
类型的数组。调用处理程序以适当的方式处理编码的方法调用,而且它返回的结果将做为代理实例上方法调用的结果返回。
b. 建立代理对象:
[java] view plain copy print?
Proxy.newProxyInstance(类加载器, Class<?>[]接口数组,回调代理对象(通常是this))
当调用目标对象方法时,经过该方法建立目标对象的代理对象,代理对象会自动调用其invoke方法调用目标对象,并将调用结果返回。
(2).cglib针对普通java类动态代理:
cglib建立动态代理时,不要求目标类必须实现接口,其工做流程以下:
a.动态代理类编写:
[java] view plain copy print?
Enhancer enhancer = new Enhancer(); //设置目标类的父类为其自己 enhancer.setSuperclass(目标类对象.getClass()); //设置回调对象为动态代理对象自己 enhancer.setCallback(this);
b.实现MethodInterceptor接口:
实现如下方法:
[java] view plain copy print?
Object intercept(Objectm代理实例,Method代理实例上调用的接口方法的Method 实例,Object[] 传入代理实例上方法调用的参数值的对象数组,MethodProxy 方法代理实例);
注意:cglib不但能够针对类动态代理,还能够针对方法动态代理。
3.面向切面编程(AOP)的基础概念:
以一个普通的java方法来举例
[java] view plain copy print?
public 返回类型 方法名(参数列表){ ——>环绕通知 方法前处理代码 ——> 前置通知 try{ 方法具体实现(方法体)……. 方法后处理代码 ——> 后置通知 }Catch(异常类型 e){ 异常处理…… ——> 例外通知 }finally{ 最后处理代理…… ——> 最终通知 } }
a. 横切关注点:如上面5个通知的位置,在java对象中,能够这些具备相似共同处理逻辑的位置加入如权限验证、事物处理、日志记录等处理逻辑的对象称为横切关注点,面向对象编程(OOP)的关注点是纵向将现实世界的事物抽象成编程的对象模型。而面向切面编程(AOP)的关注点是横向的,它将编程对象模型中拥有相似处理逻辑的地方抽象出来造成切面,而编程对象中的处理逻辑就是横切关注点。
b. 切面(Aspect):将横切关注点抽象就造成切面,与类相似,两者关注点不一样,类是事物特性的抽象,切面是横切关注点的抽象。
c. 链接点(Joinpoint):被拦截到的点,在Spring中指方法,由于spring只支持方法类型的链接点,即被拦截的方法。如上面例子的方法。
d. 切入点(Pointcut):指对链接点进行拦截的定义,是链接点的集合,即一系列被拦截方法的集合。
e. 通知(Advice):指拦截到链接点以后要作的事情,即拦截以后的逻辑处理。一般的权限验证、事物处理、日志记录等操做就是在通知中定义和完成的。
f. 目标对象(Target):代理的目标对象,即被拦截的对象。如上面例子中方法所在的对象。
g. 织入(Weave):指将切面应用到目标对象,并致使代理对象建立的过程。
h. 引入(Introduction):在不修改代码的前提下,引入能够在运行期为类动态的添加一些方法和字段。
1. Spring中支持面向切面编程(AOP)的依赖包:
Spring解压后目录中的以下3个包:
lib/aspectj/aspectjweaver.jar
lib/aspectj/aspectjrt.jar
lib/cglib/cglib-nodep-2.1-3.jar
2. 在spring中使用面向切面编程(AOP)时,须要在spring配置文件中引入aop的命名空间,即添加以下的配置:
[xhtml] view plain copy print?
xmlns:aop=”http://www.springframework.org/schema/aop” “http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd”
注意:Spring2.5之后提供两种AOP方法,即基于xml配置文件方式和基于java注解方式。
若要使用注解方式的aop,须要在spring配置文件中添加以下的对象注解方式aop的支持:
[xhtml] view plain copy print?
<aop:aspectj-autoProxy/>
6. JavaBean的包装类——BeanWrapper:
Spring经过BeanWrapper类封装一个javabean的行为,能够设置和获取其属性值,如:
[java] view plain copy print?
BeanWrapper 包装类对象 = BeanWrapperImpl(new 被包装类()); 包装类对象.setPropertyValue(“属性名”,”属性值”);
经过这种方法就能够给被包装类设置属性。
7. 基于注解方式的面向切面编程(AOP)开发:
(1).在spring配置文件中加入对注解方法的aop支持。
(2).定义切面:
和建立普通类相似,在类前加上”@Aspect”注解,代表该类是一个切面。
(3).在切面中加入切入点:
切入点就是被拦截对象方法的集合,一般切入点定义在切面中某个对切入点进行处理的方法上。使用”@Pointcut”注解,语法以下:
[java] view plain copy print?
@Pointcut(“execution(* com.test.service..*.*(..))”) public void anyMethod(){//方法名为切入点名 切入点处理 }
语法参数详解:
a. 第一个”*”:表示被拦截的方法是任意的返回类型。
b. com.test.service:这里是举一个简单的例子,表示要被拦截的包名,即被拦截的包。
c.被拦截包名后面的两个”..”:表示被拦截包下面的子包也递归进行拦截,即被拦截的子包。
d. ”..”以后的”*”:表示被拦截包及其子包下面的全部类,即被拦截的类。
e. 最后一个”*”:表示被拦截类中的全部方法,即被拦截的方法。
f. ”(..)”:表示被拦截的方法接收任意的参数,即被拦截的参数。
注意:切入点定义语法能够支持通配符,可是必定要严格遵循语法规则。如:
@Pointcut(“execution(*com.test.service..*.add*(..))”)
表示对com.test.service包及其子包下全部的类中以”add”开头的方法进行拦截。
(4).在切面中添加通知:
Spring中通知位置请参看3中的小例子。
”@Before”注解:声明前置通知。
“@AfterRutruning”注解:声明后置通知。
“@After”注解:声明最终通知。
“@AfterThrowing”注解:声明例外通知。
“@Around”注解:声明环绕通知。
一个定义通知的例子以下:
[java] view plain copy print?
@Before(“anyMethod()(切面中声明的切入点名)”) public void doAccessCheck(){ …… }
注意:环绕通知和其余4种通知的稍有不一样,环绕通知的定义方式比较特别,环绕通知在整个方法调用先后都会起做用,所以必须使用链接点对象告诉链接点在环绕通知处理以后继续其逻辑处理。其定义方式以下:
[java] view plain copy print?
@Around(切入点名) public Object doBasicProfiling(ProcedingJoinPoint pjp) throws Throwable{ …… return pjp.proceed();//该句是告诉链接点继续执行其余的操做 }
7. 基于注解方式的面向切面编程(AOP)开发的一些小技巧:
(1).获取输入参数:
如:
[java] view plain copy print?
@Before(“切入点名 && args(输入参数名)”) public void doSomething(String 输入参数名){……}
(2).获取返回结果:
如:
[java] view plain copy print?
@AfterReturning(Pointcut=”切入点名”,returning=”返回结果名”) public void dosomething(String 结果名){……}
8. 基于XML方式的面向切面编程(AOP)开发:
(1).定义切面类,在切面类中添加通知。
(2).将切面类想普通java类同样在spring配置文件中配置。
(3).在spring配置文件中添加AOP配置以下:
[xhtml] view plain copy print?
<aop:config> <!--配置切面--> <aop:aspect id=”切面id” ref=”spring配置文件中切面类的id”> <!--配置切入点--> <aop:pointcut id=”切入点id” expression=”execution(* com.test.service..*.*(..))”/> <!--配置通知--> <aop:before pointcut-ref=”切入点id” method=”切面类中相应的处理方法”/> <aop:after ……/> …… </aop:aspect> </aop:config>
9. Spring的事务处理(Spring的声明式事务处理):
事务简单来讲是指数据库中的一条最基本的操做,关于事务的详细讲解之后会在数据库相关总结中具体说明。Spring的面向切面编程(AOP)一个最重要的应用是事务管理,Spring2.5之后版本的事务管理支持基于注解的方式和基于XML文件的方式两种:
(1).基于注解方式的事务管理:
a. 在spring配置文件中添加事务管理的命名空间以下:
[xhtml] view plain copy print?
xmlns:ts=http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
b. 在spring配置文件中配置事务管理器以下:
[xhtml] view plain copy print?
<bean id=”txManager” class=”org.springframework.jdbc.datasource.DataSourceTransactionManager”> <property name=”dataSource” ref=”spring中配置的数据源bean的id”/> </bean>
c. 在spring配置文件中添加支持注解方式的事务配置项以下:
[xhtml] view plain copy print?
<tx:annotation-driventransaction-manager=”txManager(spring中配置的事务管理器bean的id)”/>
d. 使用基于注解的事务管理:
在Spring所管理的JavaEE工程中,须要使用事务的业务逻辑地方加上“@Transactional”注解。
(2).基于XML文件方式的事务管理:
a. 在spring配置文件中配置事务管理器以下:
[xhtml] view plain copy print?
<bean id=”txManager” class=”org.springframework.jdbc.datasource.DataSourceTransactionManager”> <property name=”dataSource” ref=”spring中配置的数据源bean的id”/> </bean>
b. 在spring配置文件中添加事物管理的切面以下:
[xhtml] view plain copy print?
<aop:config> <!--配置事务切入点--> <aop:pointcut id=”transactionPointcut” Expression=”execution(* com.test.service..*.*(..))”/> <!--配置事务通知--> <aop:advisor advice-ref=”txAdvice” pointcut-ref=”transactionPointcut”/> </aop:config>
c. 在spring配置文件中为事务通知添加事物处理特性以下:
[xhtml] view plain copy print?
<tx:advice id=”txAdvice” transactionManager=”txManager”> <tx:attributes> <!--这里举例将以get开头的查询方法设置为只读,不支持事务--> <tx:method name=”get*” read-only=”true” propagation=”NOT_SUPPORTED”/> <!--其余的方法设置为spring默认的事物行为--> <tx:method name=”*”/> </tx:attributes> </tx:advice>
10. Spring与Struts1集成的3种方式:
(1).方式1——使用spring中对struts1请求控制器方式:
a. 在struts1的配置文件中添加以下配置:
[xhtml] view plain copy print?
<controller> <set-property property=”processorClass” Value=”org.springframework.web.struts.DelegatingRequestProcessor”/> </controller>
b. 在Struts配置文件中的Action就不用再写type属性,在Spring配置文件中配置struts的action,配置规则以下:bean的name是struts1配置文件中action的path值。class的值为action的全路径。
注意:在spring中配置的action再也不使用id属性,由于id中不容许特殊字符如“/”。
(2).方式2——全权委托方式:
a.在struts1的配置文件中,全部的action的type属性值都写为:org.springframework.web.struts.Delegating.ActionProxy。
b. 在Spring配置文件中配置struts的action,配置规则以下:bean的name是struts1配置文件中action的path值。class的值为action的全路径。
注意:在spring中配置的action再也不使用id属性,由于id中不容许特殊字符如“/”。
(3).方式3——struts的action继承spring的ActionSupport方式:
a. struts中的全部action都继承spring的ActionSupport类。
b. 在struts的配置文件中以下配置:
[xhtml] view plain copy print?
<plug-in className=”org.springframework.web.struts.contextLoaderPlugIn”> <set-property property=”contextConfigLocation” value=”spring配置文件路径”/> </plug-in>
c. 在Struts配置文件中的Action就不用再写type属性,在Spring配置文件中配置struts的action,配置规则以下:bean的name是struts1配置文件中action的path值。class的值为action的全路径。
注意:在spring中配置的action再也不使用id属性,由于id中不容许特殊字符如“/”。