Spring学习之路3-AOP及实现AOP的三种方式
2020-03-20 16:01:53来源:博客园 阅读 ()
Spring学习之路3-AOP及实现AOP的三种方式
AOP
面向切面的程序设计(Aspect-oriented programming,AOP,又译作面向方面的程序设计、剖面导向程序设计)是计算机科学中的一种程序设计思想,旨在将横切关注点与业务主体进行进一步分离,以提高程序代码的模块化程度。通过在现有代码基础上增加额外的通知(Advice)机制,能够对被声明为“切点(Pointcut)”的代码块进行统一管理与装饰,如“对所有方法名以‘set*’开头的方法添加后台日志”。该思想使得开发人员能够将与代码核心业务逻辑关系不那么密切的功能(如日志功能)添加至程序中,同时又不降低业务代码的可读性。面向切面的程序设计思想也是面向切面软件开发的基础。
Maven 依赖
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
实现方式一:原生 Spring API 接口
public interface UserService {
void add();
int delete();
void query();
int update();
}
public class UserServiceImpl implements UserService {
@Override
public void add() {
System.out.println("function:add()");
}
@Override
public int delete() {
System.out.println("function:delete()");
return 0;
}
@Override
public void query() {
System.out.println("function:query()");
}
@Override
public int update() {
System.out.println("function:update()");
return 0;
}
}
//方法执行前的log
public class BeforeLog implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.err.println("method before log" + target.getClass().getName() + method.getName());
}
}
//方法执行后的log
public class AfterLog implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.err.println("method before log" + target.getClass().getName() + "-->" + method.getName() + "---return:" + returnValue);
}
}
<?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">
<bean id="log1" class="com.youzi.log.BeforeLog"/>
<bean id="log2" class="com.youzi.log.AfterLog"/>
<bean id="userservice" class="com.youzi.service.UserServiceImpl"/>
<!--配置AOP-->
<aop:config>
<aop:pointcut id="pointcut1" expression="execution(int com.youzi.service.UserServiceImpl.*(..))"/>
<aop:pointcut id="pointcut2" expression="execution(void com.youzi.service.*.add(..))"/>
<aop:advisor advice-ref="log1" pointcut-ref="pointcut1"/>
<aop:advisor advice-ref="log2" pointcut-ref="pointcut2"/>
</aop:config>
</beans>
execution()
切点函数语法:
execution(返回类型 包名.类名.方法名(参数类型))
也可以用*号表示所有的类型。
类名也可以用*代替表示包下面的所有类
*(..):这个星号表示方法名,*号表示所有的方法,括号中是方法的参数,两个点表示任何参数。
实现方式二:自定义类
第一种实现方式虽然实现了在方法前或者方法后添加日志,但是每实现一个功能就需要实现一个接口,通过下面的方法可以把这些方法写在一个类中
public class MethodLog {
public void beforeMethod() {
System.out.println("方法执行前");
}
public void afterMethod() {
System.out.println("方法执行后");
}
}
<?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">
<bean id="MethodLog" class="com.youzi.log.MethodLog"/>
<bean id="userservice" class="com.youzi.service.UserServiceImpl"/>
<aop:config>
<aop:aspect ref="MethodLog">
<aop:pointcut id="poindcut1" expression="execution(* com.youzi.service.*.*(..))"/>
<aop:before method="beforeMethod" pointcut-ref="poindcut1"/>
<aop:after method="afterMethod" pointcut-ref="poindcut1"/>
</aop:aspect>
</aop:config>
</beans>
上面的方法虽然简化了代码,但是目前看来不能像第一种方式一样通过反射取到执行方法的信息
实现方式三:使用注解
<?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">
<bean id="MethodLog" class="com.youzi.log.MethodLog"/>
<bean id="userservice" class="com.youzi.service.UserServiceImpl"/>
<!--在xml中声明使用注解的方式-->
<aop:aspectj-autoproxy/>
</beans>
@Aspect
public class MethodLog {
@Before("execution(* com.youzi.service.UserServiceImpl.*(..))")
public void beforeMethod() {
System.out.println("方法执行前1");
}
@After("execution(* com.youzi.service.UserServiceImpl.*(..))")
public void afterMethod() {
System.out.println("方法执行后1");
}
@Around("execution(* com.youzi.service.UserServiceImpl.update(..))")
public int aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
System.err.println("环绕前");
System.err.println(joinPoint.getSignature());
Object proceed = joinPoint.proceed();
System.err.println("环绕后");
return Integer.valueOf((Integer) proceed);
}
}
测试代码统一为
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = context.getBean("userservice", UserService.class);
userService.query();
userService.add();
userService.delete();
userService.update();
原文链接:https://www.cnblogs.com/wangjr1994/p/12528806.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- Spring系列.ApplicationContext接口 2020-06-11
- springboot2配置JavaMelody与springMVC配置JavaMelody 2020-06-11
- 学习Java 8 Stream Api (4) - Stream 终端操作之 collect 2020-06-11
- java学习之第一天 2020-06-11
- 给你一份超详细 Spring Boot 知识清单 2020-06-11
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash