本文说到spring的配置,常见的有两种:注解方式和xml文件配置方式
首先, 建立model类UserManager,代码如下:
package com.spring.model;
public class UserManager {
private int id;
private String name;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
然后, 建立一个测试service接口IUserManagerService类,代码如下:
package com.spring.service.impl;
import org.springframework.stereotype.Service;
import com.spring.model.UserManager;
import com.spring.service.IUserManagerService;
@Service("manager")
public class UserManagerServiceImpl implements IUserManagerService{
public void addUser(String userName, String password) {
System.out.println("--------------UserManager addUser-------------");
}
public void updateUser(int userId, String userName, String password) {
System.out.println("--------------UserManager updateUser-------------");
}
public void deleteUser(int userId) {
System.out.println("--------------UserManger deleteUser-------------");
}
public UserManager findUser(int userId) {
UserManager userManager = new UserManager();
System.out.println("--------------UserManager findUser-------------");
return userManager;
}
}
此时在spring的配置文件添加UserManagerServiceImpl的bean,代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<bean id="userManager" class="com.spring.service.impl.UserManagerServiceImpl" />
</beans>
配置好bean之后,我们建立一个测试类写测试用例测试我们的model,代码如下:
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.spring.service.IUserManagerService;
public class TestUserManager {
@Test
@SuppressWarnings("resource")
public void testUserManager() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
IUserManagerService userBean = (IUserManagerService) ctx.getBean("userManager");
userBean.addUser("zhaolibin", "buzhidao");
}
}
Junit运行实例后,打印如下结果:
--------------UserManager addUser-------------
一: XML配置AOP:
现在我们首先用xml文件配置方式来实现aop,spring aop中有好多切面、通知之类的理论知识在此不多说了,直接来实例,写一个切面类,在类中写上常见几个通知的方法,代码如下:
package com.spring.util;
import org.aspectj.lang.ProceedingJoinPoint;
public class InterceptorAop {
public void doBefore() {
System.out.println("========执行前置通知==========");
}
public void doAferReturning() {
System.out.println("=========执行后置通知================");
}
public void doAfter() {
System.out.println("========执行最终通知==========");
}
public void doAferThrowing() {
System.out.println("=============执行意外通知================");
}
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("=========进入判断方法===========");
Object result = pjp.proceed();
System.out.println("==========进入退出方法==========");
return result;
}
}
然后我们需要在spring的xml文件里配置切点类以及对应的方法,代码如下:
<bean id="aspetBean" class="com.spring.util.InterceptorAop"/>
<aop:config>
<aop:aspect id="aspet" ref="aspetBean">
<aop:pointcut expression="execution (* com.spring.service.impl..*.*(..))" id="cut"/>
<aop:before pointcut-ref="cut" method="doBefore"/>
<aop:after-returning pointcut-ref="cut" method="doAferReturning"/>
<aop:after pointcut-ref="cut" method="doAfter"/>
<aop:after-throwing pointcut-ref="cut" method="doAferThrowing"/>
<aop:around pointcut-ref="cut" method="doAround"/>
</aop:aspect>
</aop:config>
在此大概说下上面的切入点表达式:
1、execution (* com.spring.service.impl..*.*(..)) 2、execution : 表示执行 3、第一个*号 : 表示返回值类型, *可以是任意类型 4、com.wangku.spring.service.impl : 代表扫描的包 5、.. : 代表其底下的子包也进行拦截 6、第二个*号 : 代表对哪个类进行拦截,*代表所有类 7、第三个*号 : 代表方法 *代表任意方法 8、(..) : 代表方法的参数有无都可以
此时配置已经起作用了,再次运行测试用例可以发下打印如下结果:
========执行前置通知========== =========进入判断方法=========== --------------UserManager addUser------------- ==========进入退出方法========== ========执行最终通知========== =========执行后置通知================
细心的同学可以观察下不同的通知执行的时机。
上面就是xml配置的情况,但通常情况下 xml配置略显繁琐,所以我们来看看注解配置如何进行。
二:注解配置AOP
使用注解使一切都变得简单,首先spring配置文件中加入注解和支持注释的配置,代码如下:
<aop:aspectj-autoproxy/> <context:annotation-config /> <context:component-scan base-package="com.spring" />
最下面的一行配置是指我们要扫描的包。此时有人可能注意到了我们之前写的serviceImpl中的一句注解:@Service("manager")
此时我们的xml是支持扫描的,所以我们在spring配置文件中去掉bean的配置,值保持上面的这几行配置文件,然后在Junit里执行下面代码:
@Test
@SuppressWarnings("resource")
public void testUserManager() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
IUserManagerService userBean = (IUserManagerService) ctx.getBean("manager");
userBean.addUser("zhaolibin", "buzhidao");
}
打印出了我们意料中的结果,然后我们开始用注解的方式配置aop切面类,具体代码如下:
package com.wangku.spring.util;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class Interceptor {
@Pointcut("execution (* com.wangku.spring.service.impl..*.*(..))")
private void anyMethod() {
System.out.println("============进入anyMethod方法==============");
}
@Pointcut("execution (* com.wangku.spring.service.test..*.*(..))")
private void someMethod() {
System.out.println("============进入someMethod方法==============");
}
@Before("anyMethod()")
public void doBefore() {
System.out.println("==========执行前置通知===============");
}
@After("someMethod()")
public void doAfter() {
System.out.println("===========执行最终通知==============");
}
}
因为是切面类,所以使用@Aspect注解此类,然后用@Pointcut来指定切面表达式,此处我定义了2个切面表达式。
在spring配置文件中加入切面类的bean,如下
<bean id="interceptor" class="com.spring.util.Interceptor"/>
此时再次运行上面的Junit,会发现打印如下结果:
==========执行前置通知=============== --------------UserManager addUser-------------
注解已经执行了。接着在service下面再建立另一个test包,下面新建一个UserTestServiceImpl类进行多切面表达式的测试, 代码如下:
package com.spring.service.test;
import org.springframework.stereotype.Service;
import com.spring.model.UserManager;
import com.spring.service.IUserManagerService;
@Service("tester")
public class UserTestServiceImpl implements IUserManagerService{
public void addUser(String userName, String password) {
System.out.println("--------------UserTestServiceImpl addUser-------------");
}
public void updateUser(int userId, String userName, String password) {
System.out.println("--------------UserTestServiceImpl updateUser-------------");
}
public void deleteUser(int userId) {
System.out.println("--------------UserTestServiceImpl deleteUser-------------");
}
public UserManager findUser(int userId) {
System.out.println("--------------UserTestServiceImpl findUser-------------");
return null;
}
}
此时利用execution (* com.spring.service.test..*.*(..))切面表达式来扫描我们新建的测试类,在Junit测试用例中执行以下代码:
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
IUserManagerService userBean = (IUserManagerService) ctx.getBean("tester");
userBean.addUser("zhaolibin", "buzhidao");
执行结果如下:
--------------UserTestServiceImpl addUser------------- ===========执行最终通知==============
由此可见,我们可以配置不同的切面表达式针对不同的类进行切面处理,当然通常情况下多用于权限等的控制。
spring aop的xml文件配置还有其他不同的形式,例如通过
<aop:config> <aop:advisor advice-ref=""/> </aop:config>