Spring-AOP 分享
一、spring aop简介与应用
- Spring AOP的几个概念
- 切面(Aspect):切面就是一个关注点的模块化,如事务管理、日志管理、权限管理等;
- 连接点(Joinpoint):程序执行时的某个特定的点,在Spring中就是一个方法的执行;
- 增强(Advice):增强就是在切面的某个连接点上执行的操作,也就是事务管理、日志管理等;
- 切入点(Pointcut):切入点就是描述某一类选定的连接点,也就是指定某一类要织入通知的方法;
- 织入(Weaving):将Aspect加入到程序代码的过程,对于SpringAOP,由ProxyFactory或者ProxyFactoryBean负责织入动作。
- 目标对象(Target):就是被AOP动态代理的目标对象;
- 增强类型
- 前置增强(@Before):在目标方法执行前实施增强。
- 后置增强(@AfterReturning,@After):AfterReturning在目标方法正常执行后实施增强,如果方法抛出异常不会执行;@After增强的方法则无论是否有异常都会执行,类似finally方法。类似于finally代码块,只要应用了无论什么情况下都会执行
- 环绕增强(@Around):在目标方法执行前后实施增强。直接使用了AOP联盟定义的接口。
- 异常抛出增强(@AfterThrowing):在目标方法抛出异常后实施增强。
- 引介增强():在目标类中添加一些新的方法和属性,连接点是类级别的而非方法级别的。
- 切点表达式
| 内容项 | 示例 |
| ------------------------------- | ----------------------------------------------- |
| 任意公共方法的执行 | execution(public * (..)) |
| 任何一个以“set”开始的方法的执行 | execution( set(..)) |
| DemoService接口的任意方法的执行 | execution( com.demo.service.DemoService.(..)) |
| 定义在service包里的任意方法的执行 | execution( com.demo.service..(..)) |
| 定义在service包和所有子包里的任意类的任意方法的执行 | execution(* com.demo.service...(..)) |
| 定义在demo包和所有子包里的DemoDao类的任意方法的执行 | execution(* com.demo..DemoDao.*(..)) |
二、动态代理介绍 - jdk动态代理
JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是InvocationHandler接口和Proxy类
接口
/**
- @Classname InterfaceBean
- @Date 2021/8/4 10:53 上午
- @Created by jinhanping
/
public interface InterfaceBean {
String sayHello(String arg);
}
实现类
/* - @Classname InterfaceBeanImpl
- @Date 2021/8/4 10:52 上午
- @Created by jinhanping
*/
public class InterfaceBeanImpl implements InterfaceBean {
@Override
public String sayHello(String arg) {
System.out.println("InterfaceBeanImpl 你好 "+arg);
return "OK";
}
}
JDK 动态代理
/**
-
@Classname JdkDynamicProxy
-
@Date 2021/8/4 10:55 上午
-
@Created by jinhanping
*/
@Slf4j
public class JdkDynamicProxy implements InvocationHandler {
private InterfaceBean target;public JdkDynamicProxy(InterfaceBean target) {
this.target = target;
}@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("sayHello".equals(method.getName())) {
log.info("JDK动态代理");
}
return method.invoke(target, args);
}
}
测试
public static void main(String[] args) {
InterfaceBean bean = (InterfaceBean) Proxy.newProxyInstance(
InterfaceBean.class.getClassLoader(),
new Class<?>[] {InterfaceBean.class},
new JdkDynamicProxy(new InterfaceBeanImpl())
);
bean.sayHello("java six six six");
}
-
cglib动态代理
CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的,诸如private的方法也是不可以作为切面的。
// 目标类
public class ClassBean {public String print(String something) {
return something;
}
}
// cglib代理
public class CglibProxy implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Logger logger = LoggerFactory.getLogger(CglibProxy.class);
logger.info("cglib proxy is applyed");
return proxy.invokeSuper(obj, args);
}
}
// 测试类
public class ProxyTest {
@Test
public void testCglibProxy() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(ClassBean.class);
enhancer.setCallback(new CglibProxy());
ClassBean bean = (ClassBean)enhancer.create();
bean.print("double six six six");
}
}
上述代码中,我们通过CGLIB的Enhancer来指定要代理的目标对象、实际处理代理逻辑的对象,最终通过调用create()方法得到代理对象,对这个对象所有非final方法的调用都会转发给MethodInterceptor.intercept()方法,在intercept()方法里我们可以加入任何逻辑,比如修改方法参数,加入日志功能、安全检查功能等;通过调用MethodProxy.invokeSuper()方法,我们将调用转发给原始对象。
- 总结
Jdk动态代理获取的对象,实际是Proxy子类,且实现了代理类接口;
Cglib动态代理获取的代理对象,是代理类的子类,
原文地址:https://www.cnblogs.com/jphjava/p/15098199.html
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 动图演示:手撸堆栈的两种实现方法!
- [Go] 实战项目在线客服GO-FLY -在gin框架使用IP识别库转换IP为城市
- leetcode1552题解【二分+贪心】
- 这三年被分布式坑惨了,曝光十大坑
- 为什么删数据也提示空间不足呢?
- 前端踩坑系列《六》——让人又爱又恨的npm包
- docker运行Tomcat后访问首页报404(详细永久解决步骤)
- vue.js如何快速入门第1篇
- 3.列表-HTML基础
- 启动时间的一些分析
- 1.HTML基础知识-HTML进阶
- 浅析一个postgresql的死锁问题
- 你的第一个React App (二 ) - 应用组件开发
- 在Angular应用里使用Redux
- Elasticsearch 日志配置详解