1、基本概念
将日志记录、性能统计、安全控制等代码从业务逻辑代码中分离出来,可以独立到非业务逻辑方法中去,进而改变的时候不影响业务逻辑代码。
2、底层原理
- 底层使用动态代理
- 有接口:使用JDK动态代理
- 没有接口:使用CGLIB动态代理
Proxy动态代理
/**
loader:类加载器,接口提供
interfaces:增强方法所在的类,这个类实现的接口,支持多个接口
h:实现的接口InvocationHandler,创建代理对象,写增强的方法
*/
public static Object newProxyInstance(ClassLoader loader,Class<?>[]interfaces,InvocationHandler h)
JDK动态代理实现
- 创建接口,定义方法
- 创建接口的实现类,实现方法
- 使用proxy类创建接口代理对象
//接口
public interface IVehicle {
void run();
int speed(int speed);
void stop();}
//实现类
public class Car implements IVehicle{
@Override
public void run() {
System.out.println("点火,启动");
}
@Override
public int speed(int speed) {
int sleepTime= speed*1000/5; try { Thread.sleep(sleepTime); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("经过"+sleepTime/1000+"秒加速到"+speed+"km/h"); return speed; }
@Override
public void stop() {
System.out.println("熄火。。。");
}}
//InvocationHandler实现类
/** * 增强的逻辑 * 1、创建的是“谁”的代理对象,就要把“谁”传递过来 * 一般通过有参构造传递 */
public class MyInvacationHandler implements InvocationHandler {
private Object object;
public MyInvacationHandler(Object object) { this.object = object; }
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("记录"+method.getName()+"前状态");
Object invoke = method.invoke(object,args); System.out.println("记录"+method.getName()+"后状态");
return invoke;
}}
Class<?>[] interfaces = Car.class.getInterfaces();
ClassLoader loader = IVehicle.class.getClassLoader();
MyInvacationHandler h = new MyInvacationHandler(new Car());IVehicle vehicle = (IVehicle) Proxy.newProxyInstance(loader, interfaces,h);
vehicle.run();vehicle.speed(60);vehicle.stop();
3、AOP术语
- 连接点
类中可以被增强的方法,这些方法都成为连接点 - 切入点
实际被增强的方法就是切入点 - 通知(增强)
实际方法被增强的逻辑部分叫做通知- 前置通知
- 后置通知
- 环绕通知
- 异常通知
- 最终通知
- 切面
是一个动作,指的是将通知应用到切入点的过程
4、AOP操作的准备
基于AspectJ的AOP操作
- 基于xml配置文件实现
- 基于注解方式实现
5、切入点表达式
作用:知道对哪个类中的哪个方法进行增强
execution([权限修饰符][返回类型][类全路径][方法名称]([参数列表]))
/** *
[*]:任意权限修饰符都可以
[返回类型]:可省略
[参数列表]:可以使用两个【..】代替
例一:execution(* com.chzu.spring05.dao.add(..)) 对add方法增强
例二:execution(* com.chzu.spring05.dao.*(..)) 对类中所有方法增强
例三:execution(* com.chzu.spring05.*.*(..)) 对包中所有类中所有方法增强
*/
6、AOP操作
- 创建一个类,定义方法
- 创建增强类(编写增强逻辑)
创建方法,不同的方法代表不同的通知 - 进行通知配置
在spring配置文件中开启注解扫描
将类添加到容器中
在增强类中添加注解@Aspect
在spring配置文件中开启生成代理对象 - 配置不同类型的通知
//被增强类
@Componentpublic
class User {
public void add(){
System.out.println("添加。。。。。。。。");
}}
//增强类
@Component
@Aspectpublic
class UserProxy {
//前置通知
@Before(value = "execution(* com.chzu.spring05.aop.User.add(..))")
public void before(){
System.out.println("方法执行之前。。。。");
}}
xmlns:aop = "http://www.springframework.org/schema/aop
"xsi:schemaLocation= http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--开启Aspect生成代理对象--><aop:aspectj-autoproxy></aop:aspectj-autoproxy>
7、其他
- 公共的切入点提取
- 多个增强类对同一个方法进行增强,可以设置增强类的优先级