SpringAOP的使⽤场景及其原理
1. AOP是什么?
AOP(Aspect Oriented Programming),⾯向切⾯编程。顾明思议就是通过某个切⼊点(⽐如⽅法开始、结束)向某个切⾯(被切的对象)切⼊环绕通知(需要切⼊的逻辑代码)。⽐如⼀个类中的所有⽅法执⾏前都需要打印⽇志,那么可以通过AOP的⽅式来统⼀实现,⽽不需要在每个⽅法中都加⼊打印⽇志的代码逻辑。 Spring中可以通过配置或者注解⽅式来实现统⼀切⼊逻辑功能(⽐如事务)。
2. AOP的使⽤场景
spring aop应用场景
1) ⽇志记录、监控优化
2) 权限控制
3) 事务管理
4) 缓存
5) 持久化
.
....
3. Spring AOP的实现
Spring AOP实现由两种⽅式:
1)JDK动态代理:基于Java反射机制实现的(涉及flect包中的Proxy和InvocationHandler)。
2)Cglib动态代理:使⽤底层字节码技术,⽣成⼀个⼦类来代理⽗类,即继承被代理类。
代理⼜分为静态代理和动态代理:
1)静态代理:通过设计⼀个代理类的⽅式实现,属于预编译的⽅式,在程序运⾏前字节码⽂件就已经存在了。
2)动态代理:运⾏时⽣成字节码对象。
4. JDK动态代理实例
1)定义接⼝
// ⽤户服务接⼝
public interface IUserService {
// 插⼊⽤户名⽅法
void insert(String name);
}
2)定义接⼝实现类
public class UserServiceImpl implements IUserService {
public void insert(String name) {
System.out.println("插⼊⼀条⽤户记录,⽤户名为:" + name);
}
}
3)测试:创建动态代理对象,调⽤代理对象中的⽅法(回调InvovationHandler接⼝的实现⽅法invoke)
public class UserTest {
/**
* Object newProxyInstance(ClassLoader loader, //代理类的类加载器,与被代理类的⼀致
*                        Class<?>[] interfaces, //代理类需要实现的接⼝列表,与被代理类实现的接⼝⼀致
*                        InvocationHandler h)// 运⾏时调⽤的⽅法实际会被拦截执⾏该接⼝实现的invoke⽅法
*/
@Test
public void jdkDynamicProxyTest() {
// 创建需要被代理对象的实例
final IUserService userService = new UserServiceImpl();
// 创建代理对象
IUserService userServiceProxy = (IUserService) wProxyInstance(ClassLoader(),
new Class[]{IUserService.class},
new InvocationHandler() {
/**
* @param proxy    调⽤该⽅法的代理实例
* @param method    代理实例调⽤的接⼝⽅法
* @param args      代理实例调⽤接⼝⽅法传递的参数
* @return
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("打印⽇志......");// AOP                                                                                                                                                                                              method.invoke(userService, args);// 代表调⽤该接⼝实现类的userService实例中的⽅法
return null;
}
});
userServiceProxy.insert("lucy");
}
}
4) 输出
打印⽇志......
插⼊⼀条⽤户记录,⽤户名为:lucy
5. Cglib动态代理实例
1)定义被代理对象(作为cglib动态代理的⽗类),实现MethodInterceptor接⼝,实现回调⽅法intercept()
// 定义代理对象的⽗类,Cglib需要MethodInterceptor
// 调⽤⽗类⽅法时会被拦截,然后回调intercept⽅法
public class ProductService implements MethodInterceptor {
public void insert(String productName) {
System.out.println("插⼊商品名称为:" + productName);
}
/**
*
* @param o 代理对象
* @param method 需要被代理的⽅法
* @param objects 传递参数数组
* @param methodProxy 代理⽅法
* @return 返回值
* @throws Throwable
*/
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("打印⽇志......");
methodProxy.invoke(this, objects);
return null;
}
}
2) 测试:创建Enhancer对象,设置类加载器,动态代理⽗类,回调对象(实现MethodInterceptor接⼝的类) public class ProductTest {
@Test
public void cglibTest() {
ProductService productService = new ProductService();// 创建被代理⽗类(被代理对象)
Enhancer enhancer = new Enhancer();// 创建Cglib核⼼对象Enhancer
enhancer.Class().getClassLoader());// 设置类加载器
enhancer.Class());// 设置代理类继承的⽗类
enhancer.setCallback(productService);// 设置回调对象(MethodInterceptor实现类对象)
ProductService productServiceProxy = (ProductService) ate();// 创建代理对象
productServiceProxy.insert("苹果⼿机");
}
}
3)输出
打印⽇志......
插⼊商品名称为:苹果⼿机

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。