Spring框架——AOP面向切面编程
2017-10-13 18:58
302 查看
简介
AOP练习
使用动态代理解决问题
Spring AOP
用AspectJ注解声明切面
前置后置通知
利用方法签名编写AspectJ切入点表达式
指定切面的优先级
基于XML的配置声明切面
Spring实例练习
AOP编程时,仍然需要定义公共功能,但可以明确的定义这个功能在哪里,以什么方式应用,并且不必修改受影响的类。这样一来横切关注点就被模块化到特殊的对象(切面)里。
AOP的好处:
每个事物逻辑位于一个位置,代码不分散,便于维护和升级。
业务模块更简洁,只包含核心业务的代码。
横切关注点:
![](https://img-blog.csdn.net/20171013185728192?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQW4xMDkwMjM5Nzgy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
定义一个算法接口,含有4个方法,加减乘除。
Aop思想:
但是,这样做是有一些弊端存在的,比如:
代码混乱:
越来越多的非业务需求(日志和验证等)加入后,原有的业务方法急剧膨胀,每个方法在处理核心逻辑的同时还必须兼顾其他多个关注点。
代码分散:
以日志需求为例,只是为了满足这个单一需求,就不得不在多个模块(方法)里多次重复相同的日志代码,如果日志需求发生变化,必须修改所有模块。
那么,如何解决这些问题呢?
这就需要使用Spring的动态代理模式来完成了。
![](https://img-blog.csdn.net/20171013185717961?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQW4xMDkwMjM5Nzgy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
通知:是标注有以下5种注解的简单的Java方法
@Before:前置通知,在方法执行之前执行
@After:后置通知,在方法执行之后执行
@AfterReturning:返回通知,在方法返回结果之后执行
@AfterThrowing:异常通知,在方法抛出异常之后 @Around:环绕通知,围绕着方法执行
前置通知使用: @Before , @After注解,并将切入点表达式的值作为注解值。
![](https://img-blog.csdn.net/20171013185758876?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQW4xMDkwMjM5Nzgy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
在同一个连接点上应用不止一个切面时,除非明确指定,否则它们的优先级是不确定的。
切面的优先级可以通过实现Ordered接口或利用@Order注解指定。
实现Ordered接口,getOrder()方法的返回值越小,优先级越高。
若使用@Order注解,序号出现在注解中。
当使用XML声明切面时,需要在
在Bean配置文件中,所有的Spring AOP配置都必须定义在
使用
定义一个实体类User,实现它属性的set,get方法:
定义一个接口ScoreService,接口中定义一个登陆方法:
定义一个类ScoreServiceImpl,实现ScoreService 接口中的方法:
在applicationContext-aop2.xml中依赖注入user,并配置扫描,配置切面等。
定义切面类SpringAspect,在切面中定义相关方法。
测试类:
项目完成后的项目截图:
AOP练习
使用动态代理解决问题
Spring AOP
用AspectJ注解声明切面
前置后置通知
利用方法签名编写AspectJ切入点表达式
指定切面的优先级
基于XML的配置声明切面
Spring实例练习
简介
AOP(面向切面编程):是一种新的方法论,是对传统OOP(面向对象编程)的补充。AOP编程时,仍然需要定义公共功能,但可以明确的定义这个功能在哪里,以什么方式应用,并且不必修改受影响的类。这样一来横切关注点就被模块化到特殊的对象(切面)里。
AOP的好处:
每个事物逻辑位于一个位置,代码不分散,便于维护和升级。
业务模块更简洁,只包含核心业务的代码。
横切关注点:
AOP练习
Aop关于加减乘除的练习:定义一个算法接口,含有4个方法,加减乘除。
public interface ArithmeticCalculator(){ //加 double add(double a,double b); //减 double sub(double a,double b); //乘 double mul(double a,double b); //除 double div(double a,double b); }
Aop思想:
public void before(double a ,double b){ System.out.println(a+"and"+b); } public void after(result){ System.out.println("结果是"+result); } public double sub(double a, double b){ before(a,b); double result=a+b; after(result); return result; }
但是,这样做是有一些弊端存在的,比如:
代码混乱:
越来越多的非业务需求(日志和验证等)加入后,原有的业务方法急剧膨胀,每个方法在处理核心逻辑的同时还必须兼顾其他多个关注点。
代码分散:
以日志需求为例,只是为了满足这个单一需求,就不得不在多个模块(方法)里多次重复相同的日志代码,如果日志需求发生变化,必须修改所有模块。
那么,如何解决这些问题呢?
这就需要使用Spring的动态代理模式来完成了。
使用动态代理解决问题
代理设计模式的原理:使用一个代理将对象包装起来,然后用该代理取代原始对象,任何对原始对象的调用都要通过代理,代理对象决定是否以及何时将方法调用转到原始对象上。Spring AOP
用AspectJ注解声明切面
切面:带有@Aspect注解的Java类通知:是标注有以下5种注解的简单的Java方法
@Before:前置通知,在方法执行之前执行
@After:后置通知,在方法执行之后执行
@AfterReturning:返回通知,在方法返回结果之后执行
@AfterThrowing:异常通知,在方法抛出异常之后 @Around:环绕通知,围绕着方法执行
前置后置通知
前置通知:在方法执行之前执行的通知前置通知使用: @Before , @After注解,并将切入点表达式的值作为注解值。
利用方法签名编写AspectJ切入点表达式
最典型的切入点表达式是根据方法的签名来匹配各种方法:指定切面的优先级
指定切面的优先级:在同一个连接点上应用不止一个切面时,除非明确指定,否则它们的优先级是不确定的。
切面的优先级可以通过实现Ordered接口或利用@Order注解指定。
实现Ordered接口,getOrder()方法的返回值越小,优先级越高。
若使用@Order注解,序号出现在注解中。
@Aspect @Order(0) public class CalculaotorValidationAspect @Aspect @Order(1) public class CalculatorLoggingAspect
基于XML的配置声明切面
基于XML声明切面:当使用XML声明切面时,需要在
<beans>根元素中导入aop Schema
在Bean配置文件中,所有的Spring AOP配置都必须定义在
<aop:config>元素内部。对于每个切面而言,都要创建一个
<aop:aspect>元素来为具体的切面实现引用后端Bean实例。
使用
<aop:pointcut>来配置切点,通知元素需要用
<aop:before>等元素,method属性指定切面类中通知方法的名称。
Spring实例练习
了解了这些Spring的概念知识后,必须要有一个好的例子来理解,下面就以一个简单的小例子来举例子说明。定义一个实体类User,实现它属性的set,get方法:
public class User { private int id; private String uname; private String pwd; private int score; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUname() { return uname; } public void setUname(String uname) { this.uname = uname; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } public int getScore() { return score; } public void setScore(int score) { this.score = score; } }
定义一个接口ScoreService,接口中定义一个登陆方法:
import com.jredu.aop.entity.User; public interface ScoreService { /** * 登录 * @param user * @return */ User login(User user); }
定义一个类ScoreServiceImpl,实现ScoreService 接口中的方法:
import org.springframework.stereotype.Component; import com.jredu.aop.entity.User; import com.jredu.aop.service.ScoreService; @Component("score") public class ScoreServiceImpl implements ScoreService{ /** * 登录 */ @Override public User login(User user) { // TODO Auto-generated method stub System.out.println("登录成功!"); return user; } }
在applicationContext-aop2.xml中依赖注入user,并配置扫描,配置切面等。
<?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:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- 自动扫描标签 --> <context:component-scan base-package="com.jredu.aop"> </context:component-scan> <bean id="user" class="com.jredu.aop.entity.User" p:id="1" p:uname="张三" p:pwd="123456" p:score="0" /> <bean id="springAspect" class="com.jredu.aop.aspect.SpringAspect" /> <!-- 配置切面 --> <aop:config> <!-- 配置切点 --> <aop:pointcut expression="execution(* com.jredu.aop.service.ScoreService.login(..))" id="pointcut"/> <!-- 配置切面 --> <aop:aspect ref="springAspect"> <aop:around method="around" pointcut-ref="pointcut"/> <aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="obj"/> </aop:aspect> </aop:config> </beans>
定义切面类SpringAspect,在切面中定义相关方法。
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import com.jredu.aop.entity.User; public class SpringAspect { /** * 执行前 * @param point *//* public void before(JoinPoint point){ String method = point.getSignature().getName(); System.out.println("before method:"+method); }*/ /** * 执行后 * @param point * @throws Throwable */ public User around(ProceedingJoinPoint point) throws Throwable{ String method = point.getSignature().getName(); System.out.println("before method:"+method); //调用目标方法前 User user = (User) point.proceed(); //调用目标方法后 System.out.println("原来的用户积分:"+user.getScore()); System.out.println("after method:"+method); user.setScore(user.getScore()+100); return user; } /** * 最终返回结果 * @param point * @param obj */ public void afterReturning(JoinPoint point,Object obj){ String method = point.getSignature().getName(); System.out.println("afterReturning method:"+method); User user = (User) obj; System.out.println("现在用户的积分:"+user.getScore()); } }
测试类:
import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.jredu.aop.entity.User; import com.jredu.aop.service.ScoreService; public class ScoreTest { public static void main(String[] args) { ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext-aop2.xml"); User user = (User) app.getBean("user"); ScoreService service =(ScoreService) app.getBean("score"); service.login(user); } }
项目完成后的项目截图:
相关文章推荐
- Spring框架总结,控制反转(IOC),依赖注入(DI),面向切面编程(AOP)
- 大数据WEB阶段Spring框架 AOP面向切面编程(二)
- 大数据WEB阶段Spring框架 AOP面向切面编程(一)
- java Spring框架AOP(面向切面编程)
- Spring框架-AOP(面向切面编程)
- Spring框架(二)--AOP面向切面编程
- 【spring框架】(三)面向切面编程(AOP)
- spring框架,什么是AOP,AOP面向切面编程是怎么样的
- spring框架学习之路(一)-入门基础(2)-动态代理和AOP(面向切面编程)
- 详解Spring框架AOP(面向切面编程)
- Spring框架之AOP面向切面编程
- Spring框架(四)AOP面向切面编程
- Spring浅谈理解AOP(Aspect Oritented Program)面向切面编程
- AOP面向切面编程 (调用前, 调用时, 调用后, 出现异常时) 示例
- Spring——AOP(面向切面编程)@AspectJ注解方式
- Spring AOP(面向切面编程)【AOP快速入门】
- Spring aop 拦截器(即面向切面编程)
- AOP面向切面编程
- AOP面向切面编程配置
- Spring学习(8)--AOP(面向切面编程)基础