zbb20180824 spring ioc aop 例子
zbb_ioc_aop
https://pan.baidu.com/disk/home#/all?vmode=list&path=%2Fcode%2Fspring
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.zbb</groupId> <artifactId>zbb_test01</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>zbb_test01 Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <!-- https://mvnrepository.com/artifact/junit/junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.0.8.RELEASE</version> </dependency> <!-- aop aspect注解导包 --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.6</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.9</version> </dependency> </dependencies> <build> <finalName>zbb_test01</finalName> </build> </project>
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>springMVC</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <!-- spring 配置 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:applicationContext.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- spring-mvc 配置 --> <servlet> <servlet-name>spring-mvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spring-mvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
applicationContext.xml
<?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:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:security="http://www.springframework.org/schema/security" xsi:schemaLocation=" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- Activates annotation-based bean configuration --> <context:annotation-config /> <!-- Scans for application @Components to deploy --> <context:component-scan base-package="com.zbb" /> </beans>
spring-mvc.xml
<?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:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> <!-- 扫描控制器类 --> <context:component-scan base-package="com.zbb" /> <!-- 启动AspectJ支持 只对扫描过的bean有效 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> <!--开启注解 --> <mvc:annotation-driven /> <!-- jsp视图解析器 --> <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> </bean> </beans>
LoggerAspect.java
package com.zbb.aspect; import java.util.Arrays; import java.util.List; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Aspect // 该标签把LoggerAspect类声明为一个切面 @Order(1) // 设置切面的优先级:如果有多个切面,可通过设置优先级控制切面的执行顺序(数值越小,优先级越高) @Component // 该标签把LoggerAspect类放到IOC容器中 public class LoggerAspect { /** * 定义一个方法,用于声明切入点表达式,方法中一般不需要添加其他代码 使用@Pointcut声明切入点表达式 * 后面的通知直接使用方法名来引用当前的切点表达式;如果是其他类使用,加上包名即可 */ @Pointcut("execution(public * com.zbb.controller.*.*(..))") public void declearJoinPointExpression() { } @Pointcut("execution(public * com.zbb.service.*.*(..))") public void declearJoinPointExpression2() { } /** * 前置通知 * * @param joinPoint */ @Before("declearJoinPointExpression()") // 该标签声明次方法是一个前置通知:在目标方法开始之前执行 public void beforMethod(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); List<Object> args = Arrays.asList(joinPoint.getArgs()); System.out.println("this method " + methodName + " begin. param<" + args + ">"); } /** * 后置通知(无论方法是否发生异常都会执行,所以访问不到方法的返回值) * * @param joinPoint */ @After("declearJoinPointExpression()") public void afterMethod(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); System.out.println("this method " + methodName + " end."); } /** * 返回通知(在方法正常结束执行的代码) 返回通知可以访问到方法的返回值! * * @param joinPoit */ @AfterReturning(value = "declearJoinPointExpression()", returning = "result") public void afterReturnMethod(JoinPoint joinPoint, Object result) { String methodName = joinPoint.getSignature().getName(); System.out.println("this method " + methodName + " end.result<" + result + ">"); } /** * 异常通知(方法发生异常执行的代码) 可以访问到异常对象;且可以指定在出现特定异常时执行的代码 * * @param joinPoint * @param ex */ @AfterThrowing(value = "declearJoinPointExpression()", throwing = "ex") public void afterThrowingMethod(JoinPoint joinPoint, Exception ex) { String methodName = joinPoint.getSignature().getName(); System.out.println("this method " + methodName + " end.ex message<" + ex + ">"); } /** * 环绕通知(需要携带类型为ProceedingJoinPoint类型的参数) * 环绕通知包含前置、后置、返回、异常通知;ProceedingJoinPoin 类型的参数可以决定是否执行目标方法 * 且环绕通知必须有返回值,返回值即目标方法的返回值 * * @param joinPoint */ @Around(value = "declearJoinPointExpression()") public Object aroundMethod(ProceedingJoinPoint point) { Object result = null; String methodName = point.getSignature().getName(); try { // 前置通知 System.out.println("The method " + methodName + " start. param<" + Arrays.asList(point.getArgs()) + ">"); // 执行目标方法 result = point.proceed(); // 返回通知 System.out.println("The method " + methodName + " end. result<" + result + ">"); } catch (Throwable e) { // 异常通知 System.out.println("this method " + methodName + " end.ex message<" + e + ">"); throw new RuntimeException(e); } // 后置通知 System.out.println("The method " + methodName + " end."); return result; } /** * 前置通知 * * @param joinPoint */ @Before("declearJoinPointExpression2()") // 该标签声明次方法是一个前置通知:在目标方法开始之前执行 public void beforMethod2(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); List<Object> args = Arrays.asList(joinPoint.getArgs()); System.out.println("this method " + methodName + " begin. param<" + args + ">"); } /** * 后置通知(无论方法是否发生异常都会执行,所以访问不到方法的返回值) * * @param joinPoint */ @After("declearJoinPointExpression2()") public void afterMethod2(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); System.out.println("this method " + methodName + " end."); } /** * 返回通知(在方法正常结束执行的代码) 返回通知可以访问到方法的返回值! * * @param joinPoit */ @AfterReturning(value = "declearJoinPointExpression2()", returning = "result") public void afterReturnMethod2(JoinPoint joinPoint, Object result) { String methodName = joinPoint.getSignature().getName(); System.out.println("this method " + methodName + " end.result<" + result + ">"); } /** * 异常通知(方法发生异常执行的代码) 可以访问到异常对象;且可以指定在出现特定异常时执行的代码 * * @param joinPoint * @param ex */ @AfterThrowing(value = "declearJoinPointExpression2()", throwing = "ex") public void afterThrowingMethod2(JoinPoint joinPoint, Exception ex) { String methodName = joinPoint.getSignature().getName(); System.out.println("this method " + methodName + " end.ex message<" + ex + ">"); } /** * 环绕通知(需要携带类型为ProceedingJoinPoint类型的参数) * 环绕通知包含前置、后置、返回、异常通知;ProceedingJoinPoin 类型的参数可以决定是否执行目标方法 * 且环绕通知必须有返回值,返回值即目标方法的返回值 * * @param joinPoint */ @Around(value = "declearJoinPointExpression2()") public Object aroundMethod2(ProceedingJoinPoint point) { Object result = null; String methodName = point.getSignature().getName(); try { // 前置通知 System.out.println("The method " + methodName + " start. param<" + Arrays.asList(point.getArgs()) + ">"); // 执行目标方法 result = point.proceed(); // 返回通知 System.out.println("The method " + methodName + " end. result<" + result + ">"); } catch (Throwable e) { // 异常通知 System.out.println("this method " + methodName + " end.ex message<" + e + ">"); throw new RuntimeException(e); } // 后置通知 System.out.println("The method " + methodName + " end."); return result; } }
TestController.java
package com.zbb.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.zbb.service.TestService; @RestController @RequestMapping("test") public class TestController { @Autowired TestService testService; @RequestMapping("t1") public void t1(){ testService.t2(); } }
TestService.java
package com.zbb.service; import org.springframework.stereotype.Service; @Service public class TestService { public void t2(){ System.out.println("asdfafasdf"); } }