Spring 源码学习(4) —— 动态AOP使用示例

时间:2023-03-09 21:41:57
Spring 源码学习(4) —— 动态AOP使用示例

在实际工作中, 此bean可能是满足业务需要的核心逻辑, 例如test()方法中可能会封装着某个核心业务, 如果在test()方法前后加入日志来跟踪调试, 直接修改源码并不符合面向对象的设计模式, 而随意改动源码也会造成一定的风险。不用怕, Spring为此提供了解决方案。

1.创建用于拦截的bean

 /**
* @filename: AopBean.java
* @desc AopBean 测试类
* @author: Wang Chinda
* @blog http://www.cnblogs.com/goodcheap
* @date: 2018-05-25 11:32
* @version: v1.0
* @copyright: Copyright © 2018 ༄ྂ祸ྂྂ害ོ༘苍ྂྂ生ོ༘࿐ྂ 版权所有
* @modify_history: -
* 20180525 Wang Chinda create
* 20180525 Wang Chinda modify method()
*/
package com.itdoc.learn.source.aop.demo; /**
* @desc AopBean 测试类
* @author Wang Chinda
* @create 2018-05-25 11:32
*/
public class AopBean { public void testMethod() {
System.out.println("this is aop test method!");
}
}

2.创建Advisor

Spring中摒弃了最原始的繁杂配置方式而采用@Aspect注解对POJO进行标注, 使AOP的工作大大简化, 但是要注意, 使用@Aspect注解需要导入第三方依赖aspectjweaver。

 /**
* @filename: AspectJTest.java
* @desc aop切面控制
* @author: Wang Chinda
* @blog http://www.cnblogs.com/goodcheap
* @date: 2018-05-25 11:33
* @version: v1.0
* @copyright: Copyright © 2018 ༄ྂ祸ྂྂ害ོ༘苍ྂྂ生ོ༘࿐ྂ 版权所有
* @modify_history: -
* 20180525 Wang Chinda create
* 20180525 Wang Chinda modify method()
*/
package com.itdoc.learn.source.aop.demo; import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*; /**
* @desc aop切面控制, 创建Advisor
* @author Wang Chinda
* @create 2018-05-25 11:33
*/
@Aspect
public class AspectJTest { @Pointcut("execution(* *.*(..))")
public void test() {
} @Before("test()")
public void beforeTest() {
System.out.println("beforeTest");
} @After("test()")
public void afterTest() {
System.out.println("afterTest");
} @Around("test()")
public Object aroundTest(ProceedingJoinPoint point) {
Object obj = null;
try {
System.out.println("前置通知");
obj = point.proceed();
System.out.println("返回通知");
} catch (Throwable throwable) {
throwable.printStackTrace();
System.out.println("异常通知");
} finally {
System.out.println("后置通知");
}
return obj;
} }

3.引入第三方依赖:

 <?xml version="1.0" encoding="UTF-8"?>

 <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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.itdoc.learn.source</groupId>
<artifactId>spring-01</artifactId>
<version>1.0-SNAPSHOT</version> <name>spring-01</name> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties> <dependencies> <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.2.3.RELEASE</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<!-- aop功能 @Aspect 注解依赖包 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.10</version>
</dependency> <!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
<!--<dependency>-->
<!--<groupId>aopalliance</groupId>-->
<!--<artifactId>aopalliance</artifactId>-->
<!--<version>1.0</version>-->
<!--</dependency>--> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
<!--<dependency>-->
<!--<groupId>org.aspectj</groupId>-->
<!--<artifactId>aspectjrt</artifactId>-->
<!--<version>1.8.9</version>-->
<!--</dependency>--> <!-- https://mvnrepository.com/artifact/javax.inject/javax.inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency> <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
</dependencies> <build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

4.配置aop:在xml中开启aop功能

 <?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 使 AspectJ 注解起作用, 自动为匹配的类生成代理对象 -->
<aop:aspectj-autoproxy/> <bean id="test" class="com.itdoc.learn.source.aop.demo.AopBean"/>
<bean class="com.itdoc.learn.source.aop.demo.AspectJTest"/>
</beans>

5.测试

 /**
* @filename: AopDemoClient.java
* @desc
* @author: Wang Chinda
* @blog http://www.cnblogs.com/goodcheap
* @date: 2018-05-25 12:00
* @version: v1.0
* @copyright: Copyright © 2018 ༄ྂ祸ྂྂ害ོ༘苍ྂྂ生ོ༘࿐ྂ 版权所有
* @modify_history: -
* 20180525 Wang Chinda create
* 20180525 Wang Chinda modify method()
*/
package com.itdoc.learn.source.aop.demo; import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; /**
* @desc
* @author Wang Chinda
* @create 2018-05-25 12:00
*/
public class AopDemoClient {
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("test/aopDemo.xml");
AopBean aopBean = (AopBean) app.getBean("test");
aopBean.testMethod();
}
}

控制台输出:

五月 25, 2018 3:07:21 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1e67b872: startup date [Fri May 25 15:07:21 CST 2018]; root of context hierarchy
五月 25, 2018 3:07:21 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [test/aopDemo.xml]
五月 25, 2018 3:07:22 下午 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@5c30a9b0: defining beans [org.springframework.aop.config.internalAutoProxyCreator,test,com.itdoc.learn.source.aop.demo.AspectJTest#0]; root of factory hierarchy
前置通知
beforeTest
this is aop test method!
返回通知
后置通知
afterTest

 GitHub源码:https://github.com/wcd19901010/spring-01