Spring入门笔记--AOP
动态代理
代理模式类图
代理的基本分类: 静态代理 + 动态代理,分类的标准是 “代理关系是否在编译期确定;
JDK动态代理
样例
TargetInterface.java
public interface TargetInterface {
public void save();
}
Target.java
public class Target implements TargetInterface {
public void save(){
System.out.println("save...");
}
}
Advice.java
public class Advice {
public void before() {
System.out.println("before增强");
}
public void after() {
System.out.println("after增强");
}
}
ProxyTest.java
public class ProxyTest {
public static void main(String[] args) {
final Target target = new Target();
final Advice advice = new Advice();
TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(
// 目标对象类加载器
target.getClass().getClassLoader(),
// 目标对象相同的接口字节码对象数组
target.getClass().getInterfaces(),
// 调用代理对象任何方法,实际执行的是invoke方法
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
advice.before();
Object invoke = method.invoke(target, args);
advice.after();
return invoke;
}}
);
proxy.save();
}
}
cglib动态代理
样例
Target.java,不需要实现接口,与jdk的区别
public class Target {
public void save(){
System.out.println("save...");
}
}
ProxyTest.java
public class ProxyTest {
public static void main(String[] args) {
// 目标对象
final Target target = new Target();
// 增强对象
final Advice advice = new Advice();
// 1、创建增强器
Enhancer enhancer = new Enhancer();
// 2、设置父类(目标)
enhancer.setSuperclass(target.getClass());
// 3、设置回调
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
advice.before();
Object invoke = method.invoke(target, args);
advice.after();
return invoke;
}
});
// 4、创建代理对象
Target proxy = (Target)enhancer.create();
proxy.save();
}
}
Spring的AOP概念
术语:
- Target:代理的目标对象
- Proxy: 代理类
- Joinpoint: 连接点,spring中指方法
- PointCut: 切入点,定义对哪些Joinpoint进行拦截
- Advice: 通知/增强,拦截到JoinPoint后的操作
- Aspect:切面,PointCut+Advice
- Weaving: 织入,把增强应用到目标对象创建代理对象的过程。spring采用动态代理织入;Aspect J采用编译期织入和类装载期织入。
aop的xml配置
applicationContext.xml
<!--目标对象-->
<bean id="target" class="com.example.yihao_spring_aop.aop.Target"/>
<!--切面对象-->
<bean id="myAspect" class="com.example.yihao_spring_aop.aop.MyAspect"/>
<!--配置织入-->
<aop:config>
<aop:aspect ref="myAspect">
<aop:before method="before" pointcut="execution(public void com.example.yihao_spring_aop.aop.Target.save())"></aop:before>
</aop:aspect>
</aop:config>
test
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest {
@Autowired
private TargetInterface target;
@Test
public void test() {
target.save();
}
}
切点表达式
execution(public void com.example.yihao_spring_aop.aop.Target.save())
返回类型、包、类、方法可以是使用代表通配符
参数列表可以使用..表示任意参数
修饰符可以省略
比如:execution(void com.example..aop.Target.*(..))
aop的注解配置
applicationContext_anno.xml
<!--组件扫描-->
<context:component-scan base-package="com.example.yihao_spring_aop.anno"/>
<!--aop自动代理-->
<aop:aspectj-autoproxy/>
MyAspect.java
@Component("myAspect")
@Aspect
public class MyAspect {
@Before("execution(public void com.example.yihao_spring_aop.anno.Target.save())")
public void before() {
System.out.println("前置before");
}
public void after() {
System.out.println("后置after");
}
}
可以定义Pointcut
MyAspect.java
@Component("myAspect")
@Aspect
public class MyAspect {
@Before("pointCut()")
public void before() {
System.out.println("前置before");
}
public void after() {
System.out.println("后置after");
}
//定义PointCut表达式
@Pointcut("execution(void com.example.yihao_spring_aop.anno.*.*(..))")
public void pointCut() {}
}
分类:
Spring学习
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!