底层动态代理

程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式

导入aop的相关模块

<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>

动态感知业务类运行的状态

通知: 前置 @Before  后置 @After  环绕 @Around 异常@AfterThrowing  返回 @AfterReturning

补充环绕通知: 动态代理,手动推进目标方法运行(joinPoint.proceed() )

步骤:

编写切面类

在切面类里面  把每个方法 何时何地切入都指定好

将切面类和业务逻辑类 都添加到容器中

告诉容器 哪个是切面类@Aspect

在 xml中  <aop: aspectj-autoproxy> </aop:aspectj-autoproxy>    开启基于注解版的切面功能

注解中: 在当前的配置类加入  @EnableAspectJAutoProxy 启用基于注解的aop模式

正常代码:

@Component
public class Mathcalculator {
public int div(int i , int j) {
System.out.println("Mathcalculator--div被调用");
return i/j;
}
}

切面类:

@EnableAspectJAutoProxy
@Configuration
public class AOPConfig {
@Bean //业务逻辑类注册到容器
public Mathcalculator mathcalculator() {
return new Mathcalculator();
} @Bean // 切面类注册到容器中
public LogAspects logAspects() {
return new LogAspects();
}
}

测试:

public class test {
@Test
public void test01(){
//使用无参构造器 创建applicationContext (详情自己研究下有参构造器的方法)
AnnotationConfigApplicationContext applicationContext=
new AnnotationConfigApplicationContext(AOPConfig.class);
Mathcalculator bean = applicationContext.getBean(Mathcalculator.class);
bean.div(1, 1);
//设置需要激活的环境
applicationContext.getEnvironment().setActiveProfiles("dev","test"); //可以设置多个
//注册主配置类
applicationContext.register(Profile.class);
//启动刷新容器
applicationContext.refresh();
}
}

结果:

升级:

切面类

@Aspect
public class LogAspects {
//抽取公共的切入点表达式 本类的 如果是别的类的 写全名就OK了 @Pointcut("execution(public int com.toov5.config.Mathcalculator .*(..))" )
public void pointCut() { }
// @Before("public int com.toov5.config.Mathcalculator.div(int , int)")
@Before( "pointCut()" )
public void logStart(JoinPoint joinpoint) { //获取签名 获取方法
Object[] args = joinpoint.getArgs(); //目标方法 运行时候需要的参数表
System.out.println("除法运行@Before"+joinpoint.getSignature().getName()+"运行时参数表"+args );
}
@After( "pointCut()" ) //运行异常与否 都要执行的
public void logEnd(JoinPoint joinPoint) {
System.out.println(joinPoint.getSignature().getName()+"除法结束@After");
}
@AfterReturning(value="pointCut()", returning="result")
public void logReturn(JoinPoint joinpoint,Object result ) { //result 接受返回值
System.out.println(joinpoint.getSignature().getName()+"除法正常运行@AfterReturning,结果:"+result);
}
@AfterThrowing(value = "pointCut()", throwing="e")
public void logException(JoinPoint joinpoint, Exception e) {
System.out.println( joinpoint.getSignature().getName()+"除法异常@AfterThrowing"+e.getMessage());
}
}

配置:

@EnableAspectJAutoProxy
@Configuration
public class AOPConfig {
@Bean //业务逻辑类注册到容器
public Mathcalculator mathcalculator() {
return new Mathcalculator();
} @Bean // 切面类注册到容器中
public LogAspects logAspects() {
return new LogAspects();
}
}

测试类:

public class test {
@Test
public void test01(){
//使用无参构造器 创建applicationContext (详情自己研究下有参构造器的方法)
AnnotationConfigApplicationContext applicationContext=
new AnnotationConfigApplicationContext(AOPConfig.class);
Mathcalculator bean = applicationContext.getBean(Mathcalculator.class);
bean.div(1, 1);
//设置需要激活的环境
applicationContext.getEnvironment().setActiveProfiles("dev","test"); //可以设置多个
//注册主配置类
applicationContext.register(Profile.class);
//启动刷新容器
applicationContext.refresh();
}
}

结果:

JointPoint 要写一定要写在 参数的首位!

三步走:

1  将业务逻辑组件和切面类都加入到容器,告诉Spring哪个是切面类(@Aspect)

2 在切面类上的每一个通知方法上标注 通知注解,告诉Spring合适何地运行(切入点表达式)

3 开启基于注解的aop模式 与config上

总结:

aop的原理


加入@EnableAspectJAutoProxy  才有AOP

继续点开看

利用AspectJAutoProxyRegistrar  给自定义容器中注册bean

给容器注册一个AnnotationAwareAspectJAutoProxyCreator   自动代理创建器

可以一直追踪其父类:

实现了 SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware

后置处理器

关注后置处理器的工作  Bean初始化完成前后做的事情

BeanFactory                自动注入

AbstractAutoProxyCreator :

@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}

然后是与后置处理器有关的:

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)

有后置处理器的逻辑

AbstractAutoProxyCreator   类

AnnotationAwareAspectJAutoProxyCreator 类  initBeanFactory

启动后

1、  传入主配置类  创建 IOC容器

2、  注册配置类 调用refresh() 刷新容器

3、 registerBeanPostProcessors(beanFactory)  注册bean的后置处理器 方便拦截bean的创建

1先获取ioc容器中已经定义了需要创建对象的所有BeanPostProcessor

2给容器加别的BeanPostProcessor

3优先注册实现了PriorityOrdered接口的BeanPostProcessor

4在给容器中注册实现了Ordered接口的BeanPostProcessor

5注册没实现优先级接口的BeanPostProcessor

创建internalAutoProxyCreator的BeanPostProcessor

创建Bean的实例

populateBean 初始化Bean

1、 invokeAwareMethods() 处理Aware接口的方法回调

2、 applyBeanPostProcessorsBeforeInitialization() 应有后置处理器的BeforeInitialization( )

3、invokeInitMethods() 自定义的初始化方法

4、applyBeanPostProcessorsAfterInitialization ()  执行后置处理器的 postProcessAfterInitialization

4、BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功; aspectJAdvisorBuilder

6 把beanPostProcessor注册到BeanFactory中 调用addBeanPostProcessor(postProcessor)

Spring注解(AOP)的更多相关文章

  1. Spring注解 - AOP 面向切面编程

    基本概念: AOP:Aspect Oriented Programming,即面向切面编程 指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式 前置通知(@Before):在目标 ...

  2. 基于spring注解AOP的异常处理

    一.前言 项目刚刚开发的时候,并没有做好充足的准备.开发到一定程度的时候才会想到还有一些问题没有解决.就比如今天我要说的一个问题:异常的处理.写程序的时候一般都会通过try...catch...fin ...

  3. Spring注解AOP及单元测试junit(6)

    2019-03-10/20:19:56 演示:将xml配置方式改为注解方式 静态以及动态代理推荐博客:https://blog.csdn.net/javazejian/article/details/ ...

  4. spring 注解AOP

     aspectAnnotation的切面信息,加到了AnnotationAwareAspectJAutoProxyCreator的advisorsCache属性里面去了. 解析annotationSe ...

  5. 重新学习Spring注解——AOP

    面向切面编程——思想:在一个地方定义通用功能,但是可以通过声明的方式定义这个功能要以何种方式在何处运用,而无须修改受影响的类. 切面:横切关注点可以被模块化为特殊的类. 优点: 1.每个关注点都集中在 ...

  6. spring注解 aop

    @Resource(name="as")  为空按类型装配 @autowired 按类型 @quafiler (name="xx") 按名称 spring继承关 ...

  7. spring 注解aop调用invoke()

    public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlAp ...

  8. 一步一步深入spring(5)--使用基于注解的spring实现 AOP

    1.要利用spring aop,至少需要添加以下jar包 使用spring需要的jarspring.jar .commons-logging.jar 使用切面编程(AOP)需要的jar aspectj ...

  9. Java框架spring 学习笔记(十四):注解aop操作

    回见Java框架spring Boot学习笔记(十三):aop实例操作,这里介绍注解aop操作 首先编写一个切入点HelloWorld.java package com.example.spring; ...

  10. Spring的AOP基于AspectJ的注解方式开发3

    上上偏博客介绍了@Aspect,@Before 上篇博客介绍了spring的AOP开发的注解通知类型:@Before,@AfterThrowing,@After,@AfterReturning,@Ar ...

随机推荐

  1. java的Date类型转换为MySQL数据库的Date类型

    最近遇到一个问题,需要把java中的日期类型存放为MySQL数据库的日期类型,两个日期之间需要进行转化才能进行存储,转化代码如下: package com.alphajuns.demo1; impor ...

  2. DotNet软件开发框架

    这是我4月份发在donews博客上的文章,现在都转到博客园来,风满袖希望进一步阐述你的架构,我就将这篇文章转移到博客园.原文:http://blog.donews.com/shanyou/archiv ...

  3. 服务器证书日期无效 SSL_DATE_INVALID

    一大早上,企业微信中提示不能使用:服务器证书日期无效  错误码:SSL_DATE_INVALID 网上资料也比较少,咨询了一下企业微信客服,建议访问网址:https://www.ssllabs.com ...

  4. 【BZOJ4592】[Shoi2015]脑洞治疗仪 线段树

    [BZOJ4592][Shoi2015]脑洞治疗仪 Description 曾经发明了自动刷题机的发明家SHTSC又公开了他的新发明:脑洞治疗仪--一种可以治疗他因为发明而日益增大的脑洞的神秘装置. ...

  5. 170220、maven国内镜像 阿里云

    maven确实是一个好东西,但是在国内下载官方仓库的jar却是个大问题,速度不敢恭维,现在oschina的国内maven镜像服务已关闭,无奈之下只能另寻门路. 今天突然发现了阿里云maven国内镜像, ...

  6. Linux基础命令(二)

    作业一:1) 新建用户natasha,uid为1000,gid为555,备注信息为“master” groupadd -g 555 netasha useradd -u 1000 -g netasha ...

  7. flannel相关资料链接

    1.DockOne技术分享(十八):一篇文章带你了解Flannel http://dockone.io/article/618 2.理解Kubernetes网络之flannel网络http://ton ...

  8. 安装MySQL版本为mysql-installer-community-5.7.17.msi

    双击MySQL安装包, 勾选复选框,点击下一步: 选择仅仅服务器模式,点击下一步: 直接点击执行: 执行完成,点击下一步: 确认配置,点击下一步: 输入用户名和密码,点击下一步: 默认选项,点击下一步 ...

  9. 【Navicat连接Oracle数据库】-Navicat连接Oracle数据库设置

    1.navicat连接数据配置信息如下图所示:   点击"确定"按钮,进入到软件   按照图中所画的步骤顺序操作,最后重新启动navicat就可. 关于里面的这个文件夹 insta ...

  10. RS232串口通信

    RS232串口经常使用在PC机与FPGA通信中,用于两者之间的数据传输,因为UART协议简单.易实现,故经常使用. DB9接口只需要使用3根线,RXD(2).TXD(3)和GND(5),如下图所示.而 ...