开发步骤
- 原始功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public interface UserService { void register(User user); boolean login(String name, String password); } 1234 public class UserServiceImpl implements UserService { @Override public void register(User user) { System.out.println("UserServiceImpl.register 业务运算 + DAO"); }
@Log @Override public boolean login(String name, String password) { System.out.println("UserServiceImpl.login 业务运算 + DAO"); return true; } } 1234567891011121314
|
- 额外功能
- 切入点
- 组装切面
2、3、4 都放在了 MyAspect
类中完成:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
|
@Aspect public class MyAspect { @Around("execution(* login(..))") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("---- aspect log ----"); Object ret = joinPoint.proceed(); return ret; } } 1234567891011121314151617181920212223242526 <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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="userService" class="com.yusael.aspect.UserServiceImpl"/> <!-- 切面: 1. 额外功能 2. 切入点啊 3. 组装切面 --> <bean id="around" class="com.yusael.aspect.MyAspect"/> <!--告知 Spring 基于注解进行 AOP 编程--> <aop:aspectj-autoproxy/>
</beans> 1234567891011121314151617
|
切入点复用
切入点复用:在切面类中定义⼀个函数,上面用 @Pointcut
注解。
通过这种方式定义切入点表达式,后续更加有利于切入点复用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Aspect public class MyAspect {
@Pointcut("execution(* login(..))") public void myPoincut() {}
@Around(value = "myPoincut()") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("---- aspect log ----"); Object ret = joinPoint.proceed(); return ret; } @Around(value = "myPoincut()") public Object around1(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("---- aspect transaction ----"); Object ret = joinPoint.proceed(); return ret; } } 12345678910111213141516171819
|
切换动态代理的创建方式(JDK、Cglib)
AOP 底层实现 2 种代理创建方式:
- JDK:通过 实现接口,做新的实现类 创建代理对象
- Cglib:通过 继承父类,做新的子类 创建代理对象
默认情况 AOP 编程 底层应用 JDK动态代理创建方式。
基于注解的 AOP 开发 中切换为 Cglib:
1 2
| <aop:aspectj-autoproxy proxy-target-class="true"/> 1
|
传统的 AOP 开发 中切换为 Cglib:
1 2 3 4
| <aop:config proxy-target-class="true"> ... </aop:config> 123
|
AOP 开发中的一个坑(业务方法互相调用)
坑!:在同⼀个业务类中,进⾏业务方法间的相互调用,只有最外层的方法,才是加入了额外功能(内部的方法,通过普通的方式调用,都调用的是原始方法)。如果想让内层的方法也调用代理对象的方法,就要实现 AppicationContextAware
获得⼯厂,进而获得代理对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public class UserServiceImpl implements UserService, ApplicationContextAware { private ApplicationContext ctx; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { ctx = applicationContext; } @Override public void register(User user) { System.out.println("UserServiceImpl.register 业务运算 + DAO");
UserService userService = (UserService) ctx.getBean("userService"); userService.login("yusael", "123456"); }
@Override public boolean login(String name, String password) { System.out.println("UserServiceImpl.login 业务运算 + DAO"); return true; }
} 12345678910111213141516171819202122232425
|
AOP 知识总结