文章目录
🌕博客x主页:己不由心王道长🌕!
🌎文章说明:spring🌎
✅系列专栏:spring
🌴本篇内容:对面向切面编程即AOP进行一个详细讲解(对所需知识点进行选择阅读呀~)🌴
☕️每日一语:在人生的道路上,即使一切都失去了,只要一息尚存,你就没有丝毫理由绝望。因为失去的一切,又可能在新的层次上复得。☕️
🕤作者详情:作者是一名双非大三在校生,喜欢Java,欢迎大家探讨学习,喜欢的话请给博主一个三连鼓励。🕤
①AOP(Aspect Oriented Program)即面向切面编程。我们先回顾以下三层架构,三层架构式垂直架构,即一层对另一层提供服务,不能越级访问,分级进行运作。

上述架构是垂直分布的,而面向切面则是一个切面:
②到底是什么切面呢?
就是把各种类中冗余的代码提取出来,在需要用的时候就横向切入,就像一个切面一样。
到底是什么冗余代码呢?事务处理、异常处理等等!突然来一大堆听不懂。
③举个栗子:

比如说事务控制,在我们的业务中,虽然查询是最多的,但是添加、修改、删除也不少。查询不用提交事务,而后面的都得提交事务,在JDBC中,我们一般都手动提交事务。

都得提交事务,难道要在调用每一个方法执行完之后都编写一段提交事务的代码吗?这当然可以,不过太傻了!
④解决办法
上面看到了事务提交每次都编写代码会造成代码冗余,复用性不好,也不利于维护(事务提交与代码耦合死了)。
这是我们可以把上面重复的代码提取出来,制成一个切面,需要用的地方就声明它
⑤ 实现先行剧透:通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。
日志记录、性能统计、安全控制、事务处理、异常处理
Joint point(连接点): 连接点就是可以被拦截的点,在程序中,通常指的是方法,在Spring中只支持方法类型的连接点。在其他的地方可能支持类,这里记住方法就行了。
Pointcut(切点): 切入点就是对连接点中哪些点进行拦截的定义,对连接点(一般所有方法都可做连接点)进行条件筛选。
Advice(通知/增强): 通知就是我们拦截到切点之后,对它做的事情叫做通知或者增强,比如上面的事务,我们拦截到addUser之后,要对它增强,使其在完成方法之后增强提交事务,异常的时候发生回滚。
Aspect(切面): 即切入点和通知的结合(多个切入点共有一个通知,连在一起像不像一个面?)
Weaving(织入): 指的是在把增强的方法加入到目标对象(切点方法的拥有者)来创建新的对象的过程,spring采用的是动态代理织入(jdk动态代理和子类动态代理都有),AspectJ采用编译期织入和类装载织入。
先说一个故事吧:
有一天,小吉和他的小伙伴(连接点)去后山的山洞冒险,发现山洞里有一个shiti,小吉和其他一部分小伙伴(切点)就把这个shiti抬了出去,回家后其他抬了的小伙伴都die了,这时候小吉的身上开始发绿,爷爷看到就说:“不好,是绿shi寒警告”。
Joint point(连接点): 在上面的故事里,小吉和他的伙伴都能够被绿,就是都能被增强,可以看到绿shi寒警告是可以作用在上面所以人的身上。在Spring中,这些人就等于可以被增强的方法。
Pointcut(切点): 在上面的故事里,只有小吉和其他几名抬了这个东西的小伙伴收到了绿shi寒,其他没有抬的小伙伴则没有事。可以看出来Pointcut(切点)是有条件的Joint point(连接点),抬了的人被增强了。
Advice(通知/增强): 上面的小伙伴在抬了以后,那个东西就对他们进行了增强。
Aspect(切面): 切点和通知的结合,上面的切点就是抬了的小伙伴和小吉,通知是抬之后的作用,切点有很多,连载一起就像一个面一样。
一、创建maven工程
二、导入相关配置文件
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
<scope>runtime</scope>
</dependency>
三、添加applicationContext.xml核心配置文件
<?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"
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">
注意、上面给了Aop的命名空间。
四、定义接口和实现类
这里的实现类里面定义的方法就是连接点,至于要增强哪个方法,由程序员根据自己的业务要求,自己指定,要增强的方法就是切点

package com.bipt.ServiceAop;
/**
* @author 不止于梦想
* @date 2022/10/17 13:08
*/
public interface UserService {
public void save();
public void addUser();
}
package com.bipt.ServiceAop.impl;
import com.bipt.ServiceAop.UserService;
/**
* @author 不止于梦想
* @date 2022/10/17 13:09
*/
public class ImplUserService implements UserService {
@Override
public void save() {
System.out.println("save......");
}
@Override
public void addUser() {
System.out.println("AddUser.......");
}
}
在Spring配置文件中添加bean,把ImplUserService作为连接点

四、写通知类和在配置文件中引入
package com.bipt.ServiceAop;
/**
* 定义通知类
* @author 不止于梦想
* @date 2022/10/17 13:14
*/
public class MyAdvice {
public void advice1(){
System.out.println("吉尼抬没?");
}
}

五、定义切入点和制作切面
<aop:config>
<!--配置切点,即在哪些方法用到增强,后面是表达式-->
<aop:pointcut id="mypointCut" expression="execution( void com.bipt.ServiceAop.impl.ImplUserService.save())"/>
<!--配置切面,切面就是通知加上增强-->
<aop:aspect id="myadvice" ref="Advice">
<!--before表示前置通知,在切点执行之前执行,method则是通知里的一种方法-->
<aop:before method="advice1" pointcut-ref="mypointCut"></aop:before>
</aop:aspect>
</aop:config>
六、测试
测试要先导入测试的依赖,这里不用Spring的依赖,用junit。
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
然后编写测试类
package com.bipt;
import com.bipt.ServiceAop.UserService;
import com.bipt.ServiceAop.impl.ImplUserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import javax.annotation.processing.SupportedAnnotationTypes;
/**
* @author 不止于梦想
* @date 2022/10/17 13:47
*/
public class MyTest {
@Test
public void AopTest(){
ApplicationContext App = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) App.getBean("JointPoint");
userService.save();
}
}
测试结果如下:

可以看到结果正确,我们完成了一个入门测试,至于为什么通知在切入点之前执行是因为我们在上面配置切面的时候使用的是before,即前置增强。
通知类型大致分为六类: 分别是前置通知、后置通知、环绕通知、最终通知、异常抛出通知和引介通知。
上述通知中的引介通知我们是用不到的,这里不做介绍。
即before,在上面的例子中我们可以清楚的看到,前置通知在切入点方法执行之前执行了。这就是前置通知的作用范围。前置通知的方式一把也可以用作权限验证。
即after—running 在目标方法执行之后执行
<aop:pointcut id="after" expression="execution(* com.bipt.ServiceAop.impl.ImplUserService.save())"/>
<!--配置切面,切面就是通知加上增强-->
<aop:aspect ref="Advice">
<!--before表示后置通知,在切点执行之前执行,method则是通知里的一种方法-->
<!-- <aop:around method="advice2" pointcut-ref="mypointCut2" ></aop:around>-->
<!--后置通知-->
<aop:after-returning method="after_running" pointcut-ref="after" />

环绕通知是重点,是最重要的一个通知。环绕通知功能比较强大,它可以追加功能到方法执行的前后,这也是比较常用的方式,它可以实现其他四种通知类型的功能。
环绕通知的怎么做到在方法执行前后追加功能呢? 不难,做一个演示

即after。不管前面发生什么,最终通知都会执行。这里进行演示
<aop:aspect id="myadvice" ref="Advice">
<!--before表示后置通知,在切点执行之前执行,method则是通知里的一种方法-->
<aop:after method="advice1" pointcut-ref="mypointCut"></aop:after>
</aop:aspect>
结果:

可以看到两个方法执行循序与前置通知相反了。
二、添加事务管理
事务分为声明式事务和编程式事务,编程式事务就是JDBC的事务提交、回滚等等,这样不太方便,我们有很多的方法都要用到事务,不能需要一个就编写一个,这样太重复了。我们可以把事务抽取出来,利用Spring提高的声明式事务管理来处理。、
Spring声明式事务是基于AOP(面向切面)实现的
① 配置事务管理器
事务管理器有很多种,不同的数据访问层框架有不同的实现,而Mybatis的事务管理器为:DataSourceTransactionManager

②配置事务增强/通知(Advice)

③ 配置切面

配置代码:
<?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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
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/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop expression="com.bipt.controller"/>
</context:component-scan>
<!--导入配置文件-->
<context:property-placeholder location=" classpath:config.properties"></context:property-placeholder>
<!--配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}">
</bean>
<!--配置事务管理器-->
<bean id="transactionManager" class="
org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置事务增强-->
<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="login*" read-only="true"/>
<tx:method name="register*" propagation="REQUIRED" rollback-for="Exception,RuntimeException" read-only="false"/>
</tx:attributes>
</tx:advice>
<!--配置切面-->
<aop:config>
<aop:advisor advice-ref="transactionAdvice" pointcut-ref="transactionPointcut"></aop:advisor>
<aop:aspect ref="dataSource">
<aop:pointcut id="transactionPointcut" expression="execution(* com.bipt.service.*.*(..)) "/>
</aop:aspect>
</aop:config>
</beans>
码字不易、觉得有帮助的小伙伴动动小手给个三连,无比感谢。
我正在使用Ruby2.1.1和Rails4.1.0.rc1。当执行railsc时,它被锁定了。使用Ctrl-C停止,我得到以下错误日志:~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`gets':Interruptfrom~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`verify_server_version'from~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.
几个月前,我读了一篇关于rubygem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:
网络编程套接字网络编程基础知识理解源`IP`地址和目的`IP`地址理解源MAC地址和目的MAC地址认识端口号理解端口号和进程ID理解源端口号和目的端口号认识`TCP`协议认识`UDP`协议网络字节序socket编程接口`sockaddr``UDP`网络程序服务器端代码逻辑:需要用到的接口服务器端代码`udp`客户端代码逻辑`udp`客户端代码`TCP`网络程序服务器代码逻辑多个版本服务器单进程版本多进程版本多线程版本线程池版本服务器端代码客户端代码逻辑客户端代码TCP协议通讯流程TCP协议的客户端/服务器程序流程三次握手(建立连接)数据传输四次挥手(断开连接)TCP和UDP对比网络编程基础知识
转自:spring.profiles.active和spring.profiles.include的使用及区别说明下文笔者讲述spring.profiles.active和spring.profiles.include的区别简介说明,如下所示我们都知道,在日常开发中,开发|测试|生产环境都拥有不同的配置信息如:jdbc地址、ip、端口等此时为了避免每次都修改全部信息,我们则可以采用以上的属性处理此类异常spring.profiles.active属性例:配置文件,可使用以下方式定义application-${profile}.properties开发环境配置文件:application-dev
我完全不是程序员,正在学习使用Ruby和Rails框架进行编程。我目前正在使用Ruby1.8.7和Rails3.0.3,但我想知道我是否应该升级到Ruby1.9,因为我真的没有任何升级的“遗留”成本。缺点是什么?我是否会遇到与普通gem的兼容性问题,或者甚至其他我不太了解甚至无法预料的问题? 最佳答案 你应该升级。不要坚持从1.8.7开始。如果您发现不支持1.9.2的gem,请避免使用它们(因为它们很可能不被维护)。如果您对gem是否兼容1.9.2有任何疑问,您可以在以下位置查看:http://www.railsplugins.or
我创建了一个由于“在运行时执行的单例元类定义”而无法编码的对象(这段代码的描述是否正确?)。这是通过以下代码执行的:#defineclassXthatmyusesingletonclassmetaprogrammingfeatures#throughcallofmethod:break_marshalling!classXdefbreak_marshalling!meta_class=class我该怎么做才能使对象编码正确?是否可以从对象instance_of_x的classX中“移除”单例组件?我真的需要一个建议,因为我们的一些对象需要通过Marshal.dump序列化机制进行缓存。
我正在查看Ruby日志记录库Logging.logger方法并从sourceatgithub提出问题与这段代码有关:logger=::Logging::Logger.new(name)logger.add_appendersappenderlogger.additive=falseclass我知道类 最佳答案 这实际上删除了方法(当它实际被执行时)。这是确保close不会被调用两次的保障措施。看起来好像有嵌套的“class 关于Ruby元编程问题,我们在StackOverflow上找到一
使用Paperclip,我想从这样的URL抓取图像:require'open-uri'user.photo=open(url)问题是我最后得到一个像“open-uri20110915-4852-1o7k5uw”这样的文件名。有什么方法可以更改user.photo上的文件名?作为一个额外的变化,Paperclip将我的文件存储在S3上,所以如果我可以在初始分配中设置我想要的文件名就更好了,这样图像就会上传到正确的S3key。像这样:user.photo=open(url),:filename=>URI.parse(url).path 最佳答案
我正在开发一个xcode自动构建系统。在执行一些预构建验证时,我想检查指定的证书文件是否已被撤销。我了解securityverify-cert验证其他证书属性但不验证吊销。我如何检查撤销?我正在用Ruby编写构建系统,但我对任何语言的想法都持开放态度。我阅读了这个答案(Openssl-Howtocheckifacertificateisrevokedornot),但指向底部的链接(DoesOpenSSLautomaticallyhandleCRLs(CertificateRevocationLists)now?)进入的Material对我的目的来说有点过于复杂(用户上传已撤销的证书是一
关闭。这个问题是off-topic.它目前不接受答案。想改进这个问题吗?Updatethequestion所以它是on-topic用于堆栈溢出。关闭11年前。Improvethisquestion我不经常使用ruby-通常它加起来相当于每两个月或更长时间编写一次脚本。我的大部分编程都是使用C++进行的,这与ruby有很大不同。由于我与ruby之间的差距如此之大,我总是忘记语言的基本方面(比如解析文本文件和其他简单的东西)。我想每天练习一些基本的东西,我想知道是否有一些我可以订阅的网站,并且会向我发送当天的Ruby问题或类似的东西。有人知道这样的站点/Internet服务吗?