Spring aop的实现
对于aop的相关概念的认识
- 通知,新增处理: 已经定义好的与业务逻辑无关的一些东西,比如安全,日志,事务等。工作内容:通知定义了切面是什么以及什么时候使用。除了描述切面要完成的工 作,通知还解决何时执行这个工作,许多aop框架,包括spring都是以拦截器做通知模型,并维护一个以连接点为中心的拦截器链
- 连接点: 在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。 在Spring AOP中,一个连接点 总是 代表一个方法的执行。 通过声明一个org.aspectj.lang.JoinPoint类型的参数可以使通知(Advice)的主体部分获得连接点信息。简单来说就是可以接入通知的地方就算是连接点
- 切点(切入点): 在连接点的基础上定义切点,不一定所有的连接点都要接入通知,而接入通知的地方就叫切点
- 切面: 切点和通知的组合,通知声明了什么时候干什么,而切点声明了在哪里干
- 引入: 允许我们向现有的类添加新方法属性。这不就是把切面(也就是新方法属性:通知定义的)用到目标类中吗
- 目标: 被通知的对象,也就是真正的业务逻辑。只专注于本身
- 织入: 把切面应用到目标对象来创建新的代理对象的过程,有三种织入的方式
- 目标对象: 项目原始的Java组件。
- aop代理: AOP框架创建的对象,用来实现切面契约(aspect contract)(包括通知方法执行等功能)。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。 注意:Spring 2.0最新引入的基于模式(schema-based)风格和@AspectJ注解风格的切面声明,对于使用这些风格的用户来说,代理的创建是透明的。
在spring中通过注解的形式来实现aop的一个小案例
- 首先在spring.xml中进行配置
- 然后创建一个切面的类
- 再创建一个目标类
- 最后创建一个测试类进行测试
我们直接上代码
1.首先在spring.xml中进行相关的配置
<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: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/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--这个是扫描说在fish.aopTest下所有@Component注解的类--> <context:component-scan base-package="fish.aopTest" /> <!--这个是重点,aop是使用JDK代理还是cglib代理--> <aop:aspectj-autoproxy proxy-target-class="true" />
2.配置结束后我们进行编写切面类
package fish.aopTest; //注意不要导错了包 import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; //定义这是一个切面组件 @Aspect //用来本spring扫描的,不能少 @Component public class Agent { //定义一个切点, @Pointcut("execution(* fish.aopTest.TestAbc.*(..))") public void aTest() { } /**定义一个通知,在目标执行之后执行这个通知 其中括号里面的“aTest()”就是上面定义好的切点的方法名,两者需要一致 */ @After("aTest()") public void after() { System.out.println("结束之后"); } //定义一个通知,在目标执行之前执行这个通知 @Before("aTest()") public void before() { System.out.println("开始之前"); } }
3.然后我们创建一个目标类
package fish.aopTest; import org.springframework.stereotype.Component; //括号内的参数可以省略,省略的话就是这个类的类名(首字母小写) @Component("computer") public class Computer { public void save(){ System.out.println("电脑,电脑,便宜的电脑!"); } }
4.最后我们写个测试类来测试下
package fish.aopTest; import org.springframework.context.support.ClassPathXmlApplicationContext; public class ATest { public static void main(String[] args) { ClassPathXmlApplicationContext ct = new ClassPathXmlApplicationContext("spring.xml");//这里的spring.xml就是刚刚开始我们配置的xml的路径,不要把路径弄错了 /*这里getBean()里面的参数就是目标类的@Component()里面的参数*/ Computer computer= (Computer) ct.getBean("computer");
computer.save();
} }
这样我们的小案例就完成了,然后我们运行看下效果。(就是这么简单)
开始之前
电脑,电脑,便宜的电脑!
结束之后