目录
1.AspectJ注解驱动
- 激活AspectJ模块
1.注解激活:@EnableAspectJAutoProxy
2.XML配置: <aop:aspectj-autoproxy/>@Aspect //声明Aspect切面 @Configuration //configuration 类 @EnableAspectJAutoProxy //激活Aspect注解自动代理 public class AspectAnnotationDemo { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(AspectAnnotationDemo.class); context.refresh(); AspectAnnotationDemo aspectAnnotationDemo = context.getBean(AspectAnnotationDemo.class); System.out.println(aspectAnnotationDemo); context.close(); } }
2.编程方式实现AspectJ代理
public static void main(String[] args) { // 通过创建一个 HashMap 缓存,作为被代理对象 Map<String, Object> cache = new HashMap<>(); // 创建 Proxy 工厂(AspectJ) AspectJProxyFactory proxyFactory = new AspectJProxyFactory(cache); // 增加 Aspect 配置类 proxyFactory.addAspect(AspectConfiguration.class); // 设置暴露代理对象到 AopContext proxyFactory.setExposeProxy(true); proxyFactory.addAdvice(new MethodBeforeAdvice() { @Override public void before(Method method, Object[] args, Object target) throws Throwable { if ("put".equals(method.getName()) && args.length == 2) { System.out.println("-----"); Object proxy = AopContext.currentProxy(); System.out.printf("[MethodBeforeAdvice] 当前存放是 Key: %s , Value : %s ," + "代理对象:%s\n", args[0], args[1], proxy); } } }); // 通过代理对象存储数据 Map<String, Object> proxy = proxyFactory.getProxy(); proxy.put("1", "A"); System.out.println(cache.get("1")); }
3.@AspectJ PointCut指令与表达式
PointCut是一个筛选动作,Advice是一个具体的执行动作,一个PointCut可以对应多个Advice。
基于注解方式:
<bean id="echoService" class="com.huawei.DefaultEchoService"/>
<bean id="aspectXmlConfig" class="com.huawei.aspect.AspectXmlConfig"></bean>
<aop:config>
<aop:aspect id="AspectXmlConfig" ref="aspectXmlConfig">
<aop:pointcut id="anyPublicMethod" expression="execution(public * *(..))"/>
<aop:before method="beforeAnyPublicMethod" pointcut-ref="anyPublicMethod"/>
</aop:aspect>
</aop:config>
4.API实现Pointcut
Pointcut不会直接去运用,它要通过advisor来转换,事实上advice本来只是一个动作,它在动作之前需要关联一个pointcut,然后pointcut和advice之间需要advisor来承载的东西来做。advisor可以理解为是pointcut和advice之间的桥梁,是一个适配器,既可以通过pointcut来进行过滤,也可以通过advice进行执行动作
public static void main(String[] args) {
EchoServicePointcut echoServicePointcut = new EchoServicePointcut("echo", EchoService.class);
// ComposablePointcut pointcut = new ComposablePointcut(EchoServiceEchoMethodPointcut.INSTANCE);
// // 组合实现
// pointcut.intersection(echoServicePointcut.getClassFilter());
// pointcut.intersection(echoServicePointcut.getMethodMatcher());
// 将 Pointcut 适配成 Advisor
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(echoServicePointcut, new EchoServiceMethodInterceptor());
DefaultEchoService defaultEchoService = new DefaultEchoService();
ProxyFactory proxyFactory = new ProxyFactory(defaultEchoService);
// 添加 Advisor
proxyFactory.addAdvisor(advisor);
// 获取代理对象
EchoService echoService = (EchoService) proxyFactory.getProxy();
System.out.println(echoService.echo("Hello,World"));
}
5.@Around和@Pointcut有区别吗?
- @Pointcut是一个判断标准,@Around和@Before是执行,而@Before不需要显示触发,@Around需要显示触发调用
@Aspect
public class AspectConfiguration {
@Pointcut("execution(public * *(..))") // 匹配 Join Point
private void anyPublicMethod() { // 方法名即 Pointcut 名
System.out.println("@Pointcut at any public method.");
}
@Around("anyPublicMethod()")
public Object aroundAnyPublicMethod(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("@around at any public method.");
return pjp.proceed();
}
@Before("anyPublicMethod()")
public void beforeAnyPublicMethod() {
System.out.println("@before at any public method.");
}
}
@Configuration
@EnableAspectJAutoProxy
public class AspectJAnnotatedPointcutDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(AspectJAnnotatedPointcutDemo.class, AspectConfiguration.class);
context.refresh();
AspectJAnnotatedPointcutDemo aspectJAnnotationDemo = context.getBean(AspectJAnnotatedPointcutDemo.class);
aspectJAnnotationDemo.execute();
context.close();
}
public void execute() {
System.out.println("execute()...");
}
}
- XML实现Around advice
<bean id="aspectXmlConfig" class="com.huawei.aspect.AspectXmlConfig"></bean>
<aop:config>
<aop:aspect id="AspectXmlConfig" ref="aspectXmlConfig">
<aop:pointcut id="anyPublicMethod" expression="execution(public * *(..))"/>
<aop:around method="aroundAnyPublicMethod" pointcut-ref="anyPublicMethod"/>
<aop:before method="beforeAnyPublicMethod" pointcut-ref="anyPublicMethod"/>
</aop:aspect>
</aop:config>
- API实现Around Advice
1.为什么spring aop不需要设计Around advice? 一句话:@Around,@Before,@After都是通过拦截模式来执行的,只不过他们都是不同的拦截实现,所以不需要单独实现一个接口。
6.@AspectJ后置动作
- 方法返回后:@AfterReturning
- 异常发生后:@AfterThrowing
- finally执行:@After
7.XML配置After Advice
<bean id="aspectXmlConfig" class="com.huawei.aspect.AspectXmlConfig"></bean>
<bean id="echoServiceMethodInterceptor"
class="com.huawei.interceptor.EchoServiceMethodInterceptor"/>
<aop:config>
<!-- <aop:pointcut id="allPointcut" expression="execution(* * *(..))"/>-->
<aop:aspect id="AspectXmlConfig" ref="aspectXmlConfig">
<aop:pointcut id="anyPublicMethod" expression="execution(public * *(..))"/>
<aop:around method="aroundAnyPublicMethod" pointcut-ref="anyPublicMethod"/>
<!-- <aop:around method="aroundAnyPublicMethod" pointcut="execution(public * *(..))"/>-->
<aop:before method="beforeAnyPublicMethod" pointcut-ref="anyPublicMethod"/>
<aop:before method="beforeAnyPublicMethod" pointcut="execution(public * *(..))"/>
<aop:after method="finalizeAnyPublicMethod" pointcut-ref="anyPublicMethod"/>
<aop:after-returning method="afterAnyPublicMethod" pointcut-ref="anyPublicMethod"/>
<aop:after-throwing method="afterThrowingAnyPublicMethod" pointcut-ref="anyPublicMethod"/>
</aop:aspect>
</aop:config>
public class AspectXmlConfig {
public void beforeAnyPublicMethod() {
System.out.println("@Before any public method.");
}
public Object aroundAnyPublicMethod(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("@around at any public method.");
return pjp.proceed();
}
public void finalizeAnyPublicMethod() {
System.out.println("@After any public method.");
}
public void afterAnyPublicMethod() {
System.out.println("@AfterReturning any public method.");
}
public void afterThrowingAnyPublicMethod() {
System.out.println("@AfterThrowing any public method.");
}
}
public class AspectJSchemaBasedPointcutDemo {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:/META-IF.xml");
context.refresh();
EchoService echoService = context.getBean("echoService", EchoService.class);
System.out.println(echoService.echo("Hello,World"));
context.close();
}
}
8.API实现三种After Advice