aop (Aspect Oriented Programming), 直译: 面向侧面编程, 通过 预编译方式 或者 动态代理 实现程序功能的统一维护的一种技术
带来的好处是: 可以对通用的业务逻辑独立, 降低通用逻辑和业务逻辑的耦合, 提高通用逻辑的重用性, 提高开发效率.
统一日志记录, 性能统计, 统一授权, 事务处理, 统一异常处理.
实现利用java.lang.reflect.InvocationHandler接口, 重写其invoke方法为方法批量添加统一业务.
interface UserService {
void insert(String userName);
}
class UserServiceImpl implements UserService {
public void insert(String userName) {
System.out.println("insert " + userName);
}
}
class UserServiceProxy implements InvocationHandler {
private Object target;
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before insert");
Object result = method.invoke(target, args);
System.out.println("after insert");
return result;
}
public Object getProxy(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
}
public class CglibAopDemo {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
userService.insert("zhaoxi");// 只输出 insert zhaoxi
UserServiceProxy proxy = new UserServiceProxy();
UserService userServiceProxy = (UserService) proxy.getProxy(userService);
userServiceProxy.insert("zhaoxi");
//输出: before insert
//insert zhaoxi
//after insert
}
}
使用CGLIB库, 实现库中MethodInterceptor 接口为方法添加统一业务
使用时需单独引入CGLIB库
class UserServiceCglib implements MethodInterceptor {
private Object target;
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before insert cglib");
Object result = methodProxy.invokeSuper(o, objects);
System.out.println("after insert cglib");
return result;
}
public Object getTarget(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
}
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
UserService userServiceProxy = (UserService) new UserServiceCglib().getTarget(userService);
userServiceProxy.insert("zhaoxi");
//输出 before insert cglib
//insert zhaoxi
//after insert cglib
}
下面示例需要引入 spring-core, spring-context, spring-beans, spring-aop, spring-aspects 包
默认使用SDK动态代理, 如果使用CGLIB代理, 需要单独引入CGLIB库.
interface UserService {
void insert(String userName);
}
@Component
class UserServiceImpl implements UserService {
public void insert(String userName) {
System.out.println("insert " + userName);
}
}
@Component
@Aspect // 切面
class UserServiceAspect {
@Pointcut("execution(* fun.zhaoxi.aop.*.*(..))") //切点 参数为切点表达式
public void pointcut() {
}
@Before("pointcut()")
public void insertBefore() { //增强
System.out.println("spring aop insert before");
}
@After("pointcut()")
public void insertAfter() { //增强
System.out.println("spring aop insert after");
}
@Around("pointcut()")
public void insertAround(ProceedingJoinPoint point) throws Throwable { //增强
System.out.println("spring aop insert around before");
point.proceed();
System.out.println("spring aop insert around after");
}
@AfterReturning("pointcut()")
public void insertAfterReturning() { //增强
System.out.println("spring aop insert afterReturning");
}
@AfterThrowing("pointcut()")
public void insertAfterThrow() { //增强
System.out.println("spring aop insert afterThrow");
}
}
//spring-aop.xml: 放入resources文件夹
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<aop:aspectj-autoproxy/> <!-- 如果要使用cglib代理, 添加 proxy-target-class="true", 需引入 cglib 包 -->
<context:component-scan base-package="fun.zhaoxi.aop" /><!-- 包名是 service的包名 -->
</beans>
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-aop.xml");
UserService userService = applicationContext.getBean(UserService.class);
userService.insert("zhaoxi");
}
//输出:
// spring aop insert around before
// spring aop insert before
// insert zhaoxi
// spring aop insert around after
// spring aop insert after
// spring aop insert afterReturning
aop是spring的核心功能之一, 要玩转spring, 肯定要深入了解.
在spring中 缓存, 错误处理, 事务, 等等功能都有aop的身影, 但是真正能发挥强大功能的是 ioc + aop.