Spring AOP
1、什么是String AOP?
AOP(Ascept Oriented Programming)
1)Spring框架核心功能之一
2)Spring中的面向切面编程(区分oop)
3)Spring中业务对象的横切面
2、String AOP特点?
1)在不改变原始代码的基础上拓展新的功能业务
2)可以简化代码开发,提高效率
3、String AOP应用场景
1)系统日志处理
2)系统事务处理
3)系统安全验证
4)系统数据缓存
4、String AOP核心概念和术语
AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。其相关概念术语如下:
切面(aspect): 横切面对象,一般为一个具体类对象(可以借助@Aspect声明);
连接点(joinpoint):程序执行过程中某个特定的点,一般指被拦截到的的方法;
切入点(pointcut):对连接点拦截内容的一种定义;
通知(advice):拦截到连接点之后只要执行的方法;
目标对象(target):代理的目标对象;
通知(Advice):在切面的某个特定连接点上执行的动作,例如before,after等;
知识点术语强化:
1)切面(可以简单理解为要植入的新的业务功能,这个功能交给某个负责,这个类就是切面)
2)通知(可以简单理解为一个业务中的若干步骤,例如先做什么(before),再做什么(afterReturn),最后做什么)
3)切入点(在原有的哪些业务方法上扩展新的业务,可以将切入点理解为方法的集合)
4)连接点(可以简单理解为切入点中的一个具体方法)
5)目标对象(需要扩展功能的那个对象,一般为被代理对象)
6)代理对象(负责调用切面中的方法为目标对象植入新的功能)
5、String AOP底层通过动态代理实现
/**代理对象的处理对象,此类不是代理对象*/
public class ProxyHandler
implements InvocationHandler{
/**代表目标对象(要此对象产生代理对象)*/
private Object target;
/**
* @param target目标对象(后续要为此对象产生代理对象)
* @return 返回目标对象的代理对象
* */
public Object
newProxy(Object target){
this.target=target;
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);
}
/**在执行目标对象方法时,会默认调用此方法
* @param proxy 代理对象
* @param method 代表方法对象(通过此对象执行目标方法)
* @param args 用于接收目标方法中实际参数的值
* */
public Object
invoke(Object proxy,
Method method,
Object[] args)
throws Throwable {
long t1=System.currentTimeMillis();
Object result=
method.invoke(target, args);
long t2=System.currentTimeMillis();
System.out.println(method.getName()
+
"方法执行时间:"+(t2-t1));
return result;
}
测试类
public static void main(String[] args) {
TeamService tService=
new TeamServiceImpl();
Object obj=
new Object();
ProxyHandler pHandler=
new ProxyHandler();
TeamService proxyObject=
(TeamService)pHandler.newProxy(tService);
proxyObject.saveObject(obj);
proxyObject.updateObject(obj);
ProjectService pService=
new ProjectServiceImpl();
ProjectService pServiceProxy=(ProjectService)
pHandler.newProxy(pService);
pServiceProxy.saveObject(obj);
pServiceProxy.updateObject(obj);
}
6、Spring AOP 用注解来实现
1)配置文件
<context:component-scan
base-package="com.tong" />
<aop:aspectj-autoproxy/>
2)添加依赖
<dependencies>
<dependency>
<groupId>org.springframework
</groupId>
<artifactId>spring-context
</artifactId>
<version>4.3.9.RELEASE
</version>
</dependency>
<dependency>
<groupId>org.aspectj
</groupId>
<artifactId>aspectjrt
</artifactId>
<version>1.8.9
</version>
</dependency>
<dependency>
<groupId>org.aspectj
</groupId>
<artifactId>aspectjweaver
</artifactId>
<version>1.8.9
</version>
</dependency>
<dependency>
<groupId>Junit
</groupId>
<artifactId>junit
</artifactId>
<version>4.12
</version>
</dependency>
</dependencies>
3)切面代码
@Aspect
@Component
public class TimingAspect {
long start;
@Before(
"bean(*ServiceImpl)")
public void testBefore(){
start = System.currentTimeMillis();
System.
out.println(
"start.time="+start);
}
@After(
"bean(*ServiceImpl)")
public void testAfterReturn(){
System.
out.println(
"After");
}
@AfterThrowing(
"bean(*ServiceImpl)")
public void testAfterThrow(){
System.
out.println(
"出现异常");
}
@AfterReturning(
"bean(*ServiceImpl)")
public void testAfter(){
long end = System.currentTimeMillis();
long time = end-start;
System.
out.println(
"end.time="+end);
System.
out.println(
"耗时"+time);
}
通知说明:
通知说明:
@Before: 前置通知,切面方法在目标方法之前执行
@After: 后置通知,切面方法在目标方法之后执行
@AfterReturning:返回通知 切面方法在目标方法正常结束之后执行
@AfterThrowing: 异常通知,切面方法在目标方法异常之后执行
@Around:环绕通知, 可以在业务方法前后调用