public static void main(String[] args) {
//1、获取容器
AnnotationConfigApplicationContext
ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
//2、获取Bean对象
UserService userService = ac.getBean(“userService”, UserService.class);
//3、准备数据
User user = new User();
user.setId(“1”);
user.setUsername(“test”);
user.setNickname(“张三”);
//4、执行方法
userService.update(user);
}
}
- 运行测试类(没有切入)


1、用于开启注解AOP支持
(1)@EnableAspectJAutoProxy
1)源码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
/**
- Indicate whether subclass‐based (CGLIB) proxies are to be created
as opposed
- to standard Java interface‐based proxies. The default is {@code
false}.
*/
boolean proxyTargetClass() default false;
/**
- Indicate that the proxy should be exposed by the AOP framework as
a {@code ThreadLocal}
- for retrieval via the {@link
org.springframework.aop.framework.AopContext} class.
- Off by default, i.e. no guarantees that {@code AopContext} access
will work.
- @since 4.3.1
*/
boolean exposeProxy() default false;
}
2)说明
作用:
表示开启spring对注解aop的支持。
它有两个属性,分别是指定采用的代理方式和
是否暴露代理对象,通过AopContext可以进行访问。
从定义可以看得出,它引入AspectJAutoProxyRegister.class对象,该对象是基于注解@EnableAspectJAutoProxy注册一个AnnotationAwareAspectJAutoProxyCreator,该对象通过调用
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
注册一个aop代理对象生成器。
关于AnnotationAwareAspectJAutoProxyCreator请参
属性:
proxyTargetClass:指定是否采用cglib进行代理。默认值是false,表示使用jdk的代理。
exposeProxy: 指定是否暴露代理对象,通过AopContext可以进行访问。
使用场景: 当我们注解驱动开发时,在需要使用aop实现某些功能的情况下,都需要用到此注解。
3)示例

package cn.itbluebox.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan(“cn.itbluebox”)
@EnableAspectJAutoProxy
public class SpringConfiguration {
}
2、用于配置切面的
(1)@Aspect
1)源码
/**
-
Aspect declaration
-
@author Alexandre Vasseur
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Aspect {
/**
-
Per clause expression, defaults to singleton aspect
-
-
Valid values are “” (singleton), “perthis(…)”, etc
*/
public String value() default “”;
}
2)说明
作用:声明当前类是一个切面类。
属性:
value:默认我们的切面类应该为单例的。但是当切面类为一个多例类时,指定预处理的切入点表达式。用法是perthis(切入点表达式)。
它支持指定切入点表达式,或者是用@Pointcut修饰的方法名称(要求全限定方法名)
使用场景:此注解也是一个注解驱动开发aop的必备注解。
3)示例
@Component
@Scope(“prototype”)//注意:通常情况下我们的切面类是不需要多例的。
@Aspect(value=“execution(* cn.itbluebox.service.impl..(…))”)
public class LogUtil {
/**
- 用于配置当前方法是一个前置通知
*/
@Before(“execution(* cn.itbluebox.service.impl..(…))”)
public void printLog(){
System.out.println(“执行打印日志的功能”);
}
}
3、用于配置切入点表达式的
(1)@Pointcut
1)源码
/**
-
Pointcut declaration
-
@author Alexandre Vasseur
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Pointcut {
/**
-
The pointcut expression
-
We allow “” as default for abstract pointcut
*/
String value() default “”;
/**
- When compiling without debug info, or when interpreting pointcuts
at runtime,
-
the names of any arguments used in the pointcut are not available.
-
Under these circumstances only, it is necessary to provide the arg
names in
- the annotation ‐ these MUST duplicate the names used in the
annotated method.
- Format is a simple comma‐separated list.
*/
String argNames() default “”;
}
2)说明
作用:
此注解是用于指定切入点表达式的。
属性:
value:用于指定切入点表达式。
argNames:用于指定切入点表达式的参数。参数可以是execution中的,也可以是args中的。通常情况下不使用此属性也可以获得切入点方法参数。
使用场景:在实际开发中,当我们的多个通知需要执行,同时增强的规则确定的情况下,就可以把切入点表达式通用化。此注解就是代替xml中的<aop:pointcut>标签,实现切入点表达式的通用化。
3)示例

/*
Pointcut通用切入点表达式
execution允许
*/
@Pointcut(“execution(* cn.itbluebox.service.impl.UserServiceImpl.save(…))”)
private void pt1(){}
4、用于配置通知的
(1)@Before
1)源码
/**
-
Before advice
-
@author Alexandre Vasseur
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Before {
/**
- The pointcut expression where to bind the advice
*/
String value();
/**
- When compiling without debug info, or when interpreting pointcuts
at runtime,
- the names of any arguments used in the advice declaration are not
available.
- Under these circumstances only, it is necessary to provide the arg
names in
- the annotation ‐ these MUST duplicate the names used in the
annotated method.
- Format is a simple comma‐separated list.
*/
String argNames() default “”;
}
2)说明
作用:
被此注解修饰的方法为前置通知。前置通知的执行时间点是在切入点方法执行之
前。
属性:
value:用于指定切入点表达式。可以是表达式,也可以是表达式的引用。
argNames:用于指定切入点表达式参数的名称。它要求和切入点表达式中的参数名称
一致。通常不指定也可以获取切入点方法的参数内容。
使用场景:在实际开发中,我们需要对切入点方法执行之前进行增强, 此时就用到了前置通
知。
在通知(增强的方法)中需要获取切入点方法中的参数进行处理时,就要配合切入点表达
式参数来使用。
3)示例
/**
- 前置通知
*/
@Before(value = “pt1(user)”,argNames = “user”)
public void beforeLog(User user){
System.out.println(“执行切入点方法前记录日志”+user);
}
(2)@AfterReturning
1)源码
/**
-
After returning advice
-
@author Alexandre Vasseur
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AfterReturning {
/**
- The pointcut expression where to bind the advice
*/
String value() default “”;
/**
- The pointcut expression where to bind the advice, overrides
“value” when specified
*/
String pointcut() default “”;
/**
- The name of the argument in the advice signature to bind the
returned value to
*/
String returning() default “”;
/**
- When compiling without debug info, or when interpreting pointcuts
at runtime,
- the names of any arguments used in the advice declaration are not
available.
- Under these circumstances only, it is necessary to provide the arg
names in
- the annotation ‐ these MUST duplicate the names used in the
annotated method.
- Format is a simple comma‐separated list.
*/
String argNames() default “”;
}
2)说明
作用:
用于配置后置通知。
后置通知的执行是在切入点方法正常执行之后执行。
需要注意的是,由于基于注解的配置时,spring创建通知方法的拦截器链时,后置
通知在最终通知之后,所以会先执行@After注解修饰的方法。
属性:
value:用于指定切入点表达式,可以是表达式,也可以是表达式的引用。
pointcut:它的作用和value是一样的。
returning:指定切入点方法返回值的变量名称。它必须和切入点方法返回值名称一
致。
argNames:用于指定切入点表达式参数的名称。它要求和切入点表达式中的参数名称
一致。通常不指定也可以获取切入点方法的参数内容。
使用场景:此注解是用于配置后置增强切入点方法的。被此注解修饰方法会在切入点方法正常执行之后执行。
在我们实际开发中,像提交事务,记录访问日志,统计方法执行效率等等都可以利用后置通知实现。

User findById(String id);

public User findById(String id) {
System.out.println(“切入点方法开始执行。。。”);
User user = new User();
user.setId(id);
user.setUsername(“itbluebox”);
user.setNickname(“蓝盒子”);
return user;
}
- 修改LogUtil

/*
后置通知
*/
@AfterReturning(value = “execution(* cn.itbluebox.service.impl.. (…))&&args(param)”,
returning = “user”)
public void afterReturningLog(String param,Object user){
System.out.println(“-----------------------”);
System.out.println(“正常执行切入点方法后记录日志,切入点方法的参数 是:”+param);
System.out.println(“正常执行切入点方法后记录日志,切入点方法的返回值 是:”+user);
System.out.println(“-----------------------”);
}
- 修改测试类

package cn.itbluebox.test;
import cn.itbluebox.config.SpringConfiguration;
import cn.itbluebox.pojo.User;
import cn.itbluebox.service.UserService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class SpringAOPTest {
public static void main(String[] args) {
//1、获取容器
AnnotationConfigApplicationContext
ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
//2、获取Bean对象
UserService userService = ac.getBean(“userService”, UserService.class);
//3、准备数据
User user = new User();
user.setId(“1”);
user.setUsername(“test”);
user.setNickname(“张三”);
//4、执行方法
userService.findById(“1”);
}
}


(3)@AfterThrowing
1)源码
/**
-
After throwing advice
-
@author Alexandre Vasseur
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AfterThrowing {
/**
- The pointcut expression where to bind the advice
*/
String value() default “”;
/**
- The pointcut expression where to bind the advice, overrides
“value” when specified
*/
String pointcut() default “”;
/**
- The name of the argument in the advice signature to bind the
thrown exception to
*/
String throwing() default “”;
/**
- When compiling without debug info, or when interpreting pointcuts
at runtime,
- the names of any arguments used in the advice declaration are not
available.
- Under these circumstances only, it is necessary to provide the arg
names in
- the annotation ‐ these MUST duplicate the names used in the
annotated method.
- Format is a simple comma‐separated list.
*/
String argNames() default “”;
}
2)说明
作用:
用于配置异常通知。
属性:
value:用于指定切入点表达式,可以是表达式,也可以是表达式的引用。
pointcut:它的作用和value是一样的。
throwing:指定切入点方法执行产生异常时的异常对象变量名称。它必须和异常变量名称一致。
argNames:用于指定切入点表达式参数的名称。它要求和切入点表达式中的参数名称一致。
通常不指定也可以获取切入点方法的参数内容。
使用场景:用此注解修饰的方法执行时机是在切入点方法执行产生异常之后执行。
3)示例

package cn.itbluebox.service.impl;
import cn.itbluebox.pojo.User;
import cn.itbluebox.service.UserService;
import org.springframework.stereotype.Service;
@Service(“userService”)
public class UserServiceImpl implements UserService {
public void save(User user) {
System.out.println(“保存用户信息:”+user);
}
public void update(User user) {
System.out.println(“保存用户信息:”+user);
}
public User findById(String id) {
System.out.println(“切入点方法开始执行。。。”);
User user = new User();
user.setId(id);
user.setUsername(“itbluebox”);
user.setNickname(“蓝盒子”);
int i = 1/0;
return user;
}
}


(3)@After
1)源码
/**
-
After finally advice
-
@author Alexandre Vasseur
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface After {
/**
- The pointcut expression where to bind the advice
*/
String value();
/**
- When compiling without debug info, or when interpreting pointcuts
at runtime,
- the names of any arguments used in the advice declaration are not
available.
- Under these circumstances only, it is necessary to provide the arg
names in
- the annotation ‐ these MUST duplicate the names used in the
annotated method.
- Format is a simple comma‐separated list.
*/
String argNames() default “”;
}
2)说明
作用:
用于指定最终通知。
属性:
value:用于指定切入点表达式,可以是表达式,也可以是表达式的引用。
argNames:用于指定切入点表达式参数的名称。它要求和切入点表达式中的参数名称
一致。通常不指定也可以获取切入点方法的参数内容。
使用场景:最终通知的执行时机,是在切入点方法执行完成之后执行,无论切入点方法执行是
否产生异常最终通知都会执行。所以被此注解修饰的方法,通常都是做一些清理操作。
3)示例
/**
- 最终通知
*/
@After(value = “execution(* cn.itbluebox.service.impl..(…))”)
public void afterLog(){
System.out.println(“无论切入点方法执行是否有异常都记录日志”);
}
(4)@Around
1)源码
/**
-
Around advice
-
@author Alexandre Vasseur
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Around {
/**
- The pointcut expression where to bind the advice
*/
String value();
/**
- When compiling without debug info, or when interpreting pointcuts
at runtime,
- the names of any arguments used in the advice declaration are not
available.
- Under these circumstances only, it is necessary to provide the arg
names in
- the annotation ‐ these MUST duplicate the names used in the
annotated method.
- Format is a simple comma‐separated list.
*/
String argNames() default “”;
}
2)说明
作用:用于指定环绕通知。
属性:
value:用于指定切入点表达式,可以是表达式,也可以是表达式的引用。
argNames:用于指定切入点表达式参数的名称。
它要求和切入点表达式中的参数名称一致。通常不指定也可以获取切入点方法的参数内容。
使用场景:环绕通知有别于前面介绍的四种通知类型。它不是指定增强方法执行时机的,而是
spring为我们提供的一种可以通过编码的方式手动控制增强方法何时执行的机制。
3)示例
/**
- 环绕通知
*/
@Around(“execution(* com.itheima.service.impl..(…))”)
public Object arountPrintLog(ProceedingJoinPoint pjp){
//1.定义返回值
Object rtValue = null;
try{
//前置通知
System.out.println(“执行切入点方法前记录日志”);
//2.获取方法执行所需的参数
Object[] args = pjp.getArgs();
//3.执行切入点方法
rtValue = pjp.proceed(args);
//后置通知
System.out.println(“正常执行切入点方法后记录日志”);
}catch (Throwable t){
//异常通知
System.out.println(“执行切入点方法产生异常后记录日志”);
}finally {
//最终通知
System.out.println(“无论切入点方法执行是否有异常都记录日志”);
}
return rtValue;
}
1、@DeclareParents
(1)源码
/**
- Declare parents mixin annotation
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DeclareParents {
/**
- The target types expression
*/
String value();
/**
-
Optional class defining default implementation
-
of interface members (equivalent to defining
-
a set of interface member ITDs for the
-
public methods of the interface).
*/
Class defaultImpl() default DeclareParents.class;
// note ‐ a default of “null” is not allowed,
// hence the strange default given above.
}
(2)说明
作用:
用于给被增强的类提供新的方法。(实现新的接口)
属性:
value:用于指定目标类型的表达式。当在全限定类名后面跟上+时,表示当前类及其子类
defaultImpl:指定提供方法或者字段的默认实现类。
使用场景:当我们已经完成了一个项目的某个阶段开发,此时需要对已完成的某个类加入一些新的方法,我们首先想到的是写一个接口,然后让这些需要方法的类实现此接口,但是如果目标类非常复杂,牵一发而动全身,改动的话可能非常麻烦。
此时就可以使用此注解,然后建一个代理类,同时代理该类和目标类。
(3)示例


package cn.itbluebox.service;
import cn.itbluebox.pojo.User;
public interface ValidateService {
boolean checkUser(User user);
}


package cn.itbluebox.service.impl;
import cn.itbluebox.pojo.User;
import cn.itbluebox.service.ValidateService;
public class ValidateServiceImpl implements ValidateService {
@Override
public boolean checkUser(User user) {
if(user.getNickname().contains(“孙子”)){
return false;
}
return true;
}
}
- 创建MyPointcut


package cn.itbluebox.pointcut;
import org.aspectj.lang.annotation.Pointcut;
public class MyPointcut {
/**
- 用于定义通用的切入点表达式
*/
@Pointcut(value = “execution(* cn.itbluebox.service.impl..(…))”)
public void pointcut1(){}
}
- AOP切面类的配置

package cn.itbluebox.utils;
import cn.itbluebox.pojo.User;
import cn.itbluebox.service.ValidateService;
import cn.itbluebox.service.impl.ValidateServiceImpl;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class LogUtil {
@DeclareParents(value =
“cn.itbluebox.service.UserService+”, defaultImpl =
ValidateServiceImpl.class)
private ValidateService validateService;
先自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。



由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以扫码领取!
最后
作为过来人,小编是整理了很多进阶架构视频资料、面试文档以及PDF的学习资料,针对上面一套系统大纲小编也有对应的相关进阶架构视频资料


public void pointcut1(){}
}
- AOP切面类的配置

package cn.itbluebox.utils;
import cn.itbluebox.pojo.User;
import cn.itbluebox.service.ValidateService;
import cn.itbluebox.service.impl.ValidateServiceImpl;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class LogUtil {
@DeclareParents(value =
“cn.itbluebox.service.UserService+”, defaultImpl =
ValidateServiceImpl.class)
private ValidateService validateService;
先自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-OSipTOHL-1711378361497)]
[外链图片转存中…(img-4Q5vDnY0-1711378361498)]
[外链图片转存中…(img-2iq3KihF-1711378361498)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以扫码领取!
最后
作为过来人,小编是整理了很多进阶架构视频资料、面试文档以及PDF的学习资料,针对上面一套系统大纲小编也有对应的相关进阶架构视频资料
[外链图片转存中…(img-sNX6MViK-1711378361498)]
[外链图片转存中…(img-AxKT81uo-1711378361498)]
需要更多Java资料的小伙伴可以帮忙点赞+关注,点击传送门,即可免费领取!
本文围绕Spring AOP展开,分析了常用注解。介绍了开启注解AOP支持的@EnableAspectJAutoProxy,配置切面、切入点表达式、通知的注解,还提及用于扩展目标类的注解。给出各注解的源码、说明及示例,帮助开发者理解和使用Spring AOP。
3089

被折叠的 条评论
为什么被折叠?



