1、AOP面向切面编程
AOP(Aspect Oriented Programming)面向切面编程。通过预编译方式和运行期动态代理实现程序功能的统一维护。
AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
1、这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。
2、将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。
AOP其实是将琐碎的事务和逻辑代码相分离,以便我们更好的关注逻辑代码
代码逻辑比如是插入一条数据,那么琐碎事务就包括获取连接和关闭连接,事务开始,事务提交。
切面就是指在大堆繁琐事务中的逻辑代码。
AOP原理
AOP采取横向的抽取机制,取代传统由于继承产生的代码重复
AOP是在编译时期运用反射机制,通过代理方式向目标类植入代码
2、重要概念
1、Target :目标类,需要被增强程序。
2、JoinPoint:连接点,目标类中可以被增强的方法。例如:addUser、updateUser
3、PointCut:切入点,已经被增强的连接点JointPoint。增强已经生效。例如:addUser
切入点 是 连接点 一个子集。
4、Advice:增强/通知,用于增强的方法。例如:before() /after()
5、Intruduction 引介,特殊通知:类添加方法或字段等。(了解)
6、Weaving 织入:将通知(增强)应用目标类,生产代理过程。
7、Proxy:代理
8、Aspect 切面:将通知Adivce 和 切入点 PointCut 结合在一起。
入门Demo
1、UserService代码
public interface UserService {
void addUser();
void deleteUser();
}
2、UserServiceImpl代码
public class UserServiceImpl implements UserService{
public void addUser() {
// TODO Auto-generated method stub
System.out.println("user add");
}
public void deleteUser() {
// TODO Auto-generated method stub
System.out.println("user delete");
}
}
3、MyAspect代码
public class MyAspect implements MethodInterceptor {
public Object invoke(MethodInvocation arg0) throws Throwable {
// TODO Auto-generated method stub
System.out.println("开启事务");
//执行目标方法
Object obj=arg0.proceed();
System.out.println("关闭事务");
return obj;
}
}
4、beans.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"
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">
<!-- 1 目标类 -->
<bean id="userServiceId" class="com.example.demo1.UserServiceImpl"></bean>
<!-- 2 确定通知 -->
<bean id="myAspect" class="com.example.demo1.MyAspect"></bean>
<!-- 3 编写aop,通过配置文件,将通知去增强目标类
* 如果要使用切入点表达式,必须导入apsjectj的jar: com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
-->
<aop:config>
<!-- 3.1 声明切入点(确定对那些方法进行增强) -->
<aop:pointcut expression="execution(* com.example.demo1.*.*(..))" id="myPointCut"/>
<!-- 3.2声明切面:切入点 和 通知 结合
* advisor :特殊的切面,只有一个切入点 和一个通知
* aspect:就是切面,可以有多个切入点和多个通知
-->
<aop:advisor advice-ref="myAspect" pointcut-ref="myPointCut"/>
</aop:config>
</beans>
5、测试
@Test
public void testAop() {
///com/example/demo1/beans.xml
String xmlPath = "com/example/demo1/beans.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
UserService userService = (UserService) applicationContext
.getBean("userServiceId",UserService.class);
userService.addUser();
userService.deleteUser();
}
3、Aspect J
AspectJ是一个基于Java语言的AOP框架
@Aspect 是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面
新版本Spring框架,建议使用AspectJ方式来开发AOP
AspectJ规定6种通知类型:
before:前置通知,目标方法前执行。
afterReturning:后置通知,目标方法后执行。
around:环绕通知,目标方法前后执行。
afterThrowing:抛出通知,目标方法发生异常。
after:最终通知,无论什么情况都会执行。
declare-parents:引介
Aspectj演示demo(注解方式)
1、OrderService类
public interface OrderService {
void addOrder();
void updateOrder();
}
2、OrderService实现
@Service
public class OrderServiceImpl implements OrderService {
public void addOrder() {
// TODO Auto-generated method stub
System.out.println("addOrder service");
}
public void updateOrder() {
// TODO Auto-generated method stub
System.out.println("updateOrder service");
}
}
3、MyAspect代码
package com.example.aspect;
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.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class MyAspect {
@Before("execution(* com.example.aspect.*.*(..))")
public void myBefore(JoinPoint joinPoint) {
System.out.println("前置通知----" + joinPoint.getSignature().getName());
}
@AfterReturning(value = "execution(* com.example.aspect.*.*(..))", returning = "val")
public void myAfterReturning(JoinPoint joinPoint, Object val) {
System.out.println("后置通知" + val);
}
// 方法有要求:返回值Object,参数类型 ProceedingJoinPoint,抛出异常 Throwable
@Around("execution(* com.example.aspect.*.*(..))")
public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕前------");
// 执行目标类
Object obj = joinPoint.proceed();
System.out.println("环绕后------");
return obj;
}
// @AfterThrowing(value="execution(* cn.itcast.d_aspectj.b_annotation.*.*(..))",
// throwing="e")
public void myAfterThrowing(JoinPoint joinPoint, Throwable e) {
System.out.println("抛出异常通知" + e.getMessage());
}
@After("myPointCut()")
public void myAfter() {
System.out.println("最终");
}
// 共享表达式,添加到一个特殊的方法上,私有,没有返回值,方法名称自定义
// * 使用时,在注解中,当成方法调用。例如:@After("myPointCut()")
@Pointcut("execution(* com.example.aspect.*.*(..))")
private void myPointCut() {
}
}
4、beans.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"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 1.注解类可以使用扫描 ,生成<bean>-->
<context:component-scan base-package="com.example.aspect"></context:component-scan>
<!-- 2.使AspectJ 自动代理 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
5、测试用例
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:com/example/aspect/beans.xml")
public class AspectTest {
@Autowired
private OrderService orderService;
@Test
public void aspectTest1() {
orderService.addOrder();
orderService.updateOrder();
}
}
运行结果