一、AOP来也
1、概念
- 面向切面编程(Aspect Oriented Programming)
- 跨模块的代码共享
- 面向对象编程的一种补充,用于处理一些具有横切性质的系统级服务
2、名词必备
- 切面Aspect 切面编程的完整定义模块,比如日志切面
- 连接点Join point 能够植入切面的部分,比如方法前后,抛出异常时都
- 通知Advice 要对切面添加的功能代码,比如 安全,事物,日志等功能代码
- 切入点Pointcut 指定具体的拦截地点。可以通过spEL指定连接点
- 引入Introduction 对目标类添加新方法及属性
- 目标对象Target objec 被切面切的对象
- 代理proxy 实现AOP的一种原理
- 织入Weaving 把切面应用到目标对象来创建新的代理对象的过程
3、应用场景
-
权限验证
-
性能追踪
-
日志追踪
-
懒加载
二、AOP代理
1、代理
- 静态代理(Static Proxy) 由程序员创建或特定工具自动生成源代码,再对其编译
- 如果接口加一个方法,所有的实现类和代理类里都需要做个实现
- 增加了代码的复杂度
- 动态代理就可以避免这个缺点
- 动态代理(Dynamic Proxy) 在程序运行时,运用反射机制动态创建而成。
- 动态代理类只能代理接口
- 代理类都需要实现InvocationHandler类,实现invoke方法
- 该invoke方法就是调用被代理接口的所有方法时需要调用
- 该invoke方法返回的值是被代理接口的一个实现类
2、AOP实现
- pox.xml配置springframework、aspectj、aspectj
<!-- spring aop支持包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
- 建立LogAdvice类,写日志通知类和性能统计
阿package com.chinasoft.spring.skillpig.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;
import java.util.Arrays;
/**
* 日志通知类
*/
@Component
public class LogAdvice {
public void logBefore(JoinPoint joinPoint){
String builder = getFullMethodButcher(joinPoint);
System.out.println(builder);
}
private String getFullMethodButcher(JoinPoint joinPoint) {
StringBuilder builder=new StringBuilder();
//从切入点获取类名
builder.append(joinPoint.getTarget().getClass().getCanonicalName());
builder.append("#");
//从切入点获取方法名
builder.append(joinPoint.getSignature().getName());
builder.append("#");
//获取方法参数
builder.append(Arrays.toString(joinPoint.getArgs()));
return builder.toString();
}
/**
* 性能统计
* @param pjp
* @return
*/
public Object performanceStat(ProceedingJoinPoint pjp){
String butcher=getFullMethodButcher(pjp);
Object result=null;
try {
//方法执行前时间
long before=System.currentTimeMillis();
//执行方法
Object[] args=pjp.getArgs();
boolean warnFlag=false;
for (Object arg:args){
if (arg instanceof String){
String s=(String)arg;
if (s.contains(("李"))){
warnFlag=true;
System.err.println("不是整形Integer");
break;
}
}
}
if (!warnFlag){
//执行该方法
result=pjp.proceed();
}else {
return null;
}
//执行方法后
long after=System.currentTimeMillis();
System.out.println(butcher+"耗时, "+(after-before)+"毫秒");
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return butcher;
}
}
- 建立KillPigService接口,并有一个订单方法
package com.chinasoft.spring.skillpig.aop.services;
public interface KillPigServices {
/**
* 杀猪预定方法
* @param pigCount 有几头待宰大猪
* @return
*/
String order(int pigCount);
}
- 建立KillPigServiceImpl类,实现KillPigService接口
package com.chinasoft.spring.skillpig.aop.services.impl;
import com.chinasoft.spring.skillpig.aop.services.KillPigServices;
import org.springframework.stereotype.Component;
@Component("killPigServicesImpl")
public class KillPigServicesImpl implements KillPigServices {
@Override
public String order(int pigCount) {
System.out.println("预定杀肥猪订单方法中。。。。");
String s=null;
for(int i=0;i<10000;i++){
s+=i;
}
return null;
}
}
三、代理实现
1、静态代理
- 一个接口,两个实现类
- 一个原始类,一个代理类
2、代理实现
- 建立KillPigService接口,写kill方法
package com.chinasoft.spring.skillpig.proxy;
public interface KillPigService {
double kill(String pigname);
}
- 建立原始类KillPigServiceImpl,实现KillService接口
package com.chinasoft.spring.skillpig.proxy;
public class KillPigServiceImpl implements KillPigService {
@Override
public double kill(String pigname) {
System.out.println("屠宰"+pigname);
return 1000;
}
}
- 建立代理类,实现KillPigImplProxy接口
package com.chinasoft.spring.skillpig.proxy;
public class KillPigServiceImplProxy implements KillPigService {
private KillPigServiceImpl killPigServiceImpl=new KillPigServiceImpl();
@Override
public double kill(String pigname) {
System.out.println("执行KillPigServiceImpl方法"+pigname);
//方法执行前时间
long before=System.currentTimeMillis();
double result=killPigServiceImpl.kill(pigname);
//方法执行后时间
long after=System.currentTimeMillis();
System.out.println("执行killPigServiceImpl方法结束,耗时:"+(after-before)+"毫秒");
return result;
}
}