- AOP Aspect Oriented Programing 面向切面编程
- AOP采用横向抽取机制,取代了传统纵向继承体系重复性代码(性能监视、事务管理、安全性检查、缓存)
- Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码
- Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点
- Pointcut(切入点):所谓切入点是指我们要对哪些Joinpoint进行拦截的定义
- Advice(增强/通知):所谓通知是指拦截到Joinpoint之后所要做的事情。通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)
- Introduction(引介):引介是一种特殊的通知,在不修改类代码的前提下,Introduction可以在运行期为类动态添加一些方法或者Field
- Target(目标对象):代理的目标对象
- Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织入,而AspectJ采用编译期织入和类加载期织入
- Proxy(代理):一个类被AOP织入增强后,就产生了一个结果代理类
- Aspect(切面):是窃读点和通知(引介)的结合
只能增强实现了接口的类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MyJdkProxy implements InvocationHandler {
private UserDao userDao;
public MyJdkProxy(UserDao userDao){
this.userDao = userDao;
}
public Object createProxy() {
return Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if("save".equals(method.getName())){
System.out.println(" 权限校验");
return method.invoke(userDao , args);
}
return method.invoke(userDao , args);
}
}
使用CGLIB生成代理
- 对于不使用接口的业务类,无法使用JDK动态代理
- CGlib采用非常底层字节码技术,可以为一个类创建子类,解决无接口代理问题
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class MyCglibProxy implements MethodInterceptor {
private ProductDao productDao;
public MyCglibProxy(ProductDao productDao){
this.productDao = productDao;
}
public Object createProxy(){
//1.创建核心类
Enhancer enhancer = new Enhancer();
//2.设置父类
enhancer.setSuperclass(productDao.getClass());
//3.设置回调
enhancer.setCallback(this);
//4.生成代理
Object proxy = enhancer.create();
return proxy;
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
if("save".equals(method.getName())){
System.out.println("权限校验");
return methodProxy.invokeSuper(proxy , args);
}
return methodProxy.invokeSuper(proxy , args);
}
}
代理知识总结
- Spring在运行期,生成动态代理对象,不需要特殊的编译器
- Spring AOP的底层就是通过JDK动态代理或CGLib动态代理技术,为目标Bean执行横向织入
1.若目标对象实现了若干接口,spring使用JDK的java.lang.reflect.Proxy类代理
2.若目标对象没有实现任何接口,spring使用CGLIB库生成目标对象的子类 - 程序中应优先对接口创建代理,便于程序解耦维护
- 标记为final的方法,不能被代理,因为无法进行覆盖
1.JDK动态代理,是针对接口生成子类,接口中方法不能使用final修饰
2.CGLib是针对目标类生成子类,因此类或方法不能使用final - Spring只支持方法的连接点,不提供属性的连接点



