spring 框架之 aop 编程的两种配置方式
- 准备
首先我们创建一个Study 类,代码如下:
public class Study {
public void study(){
System.out.println("正在学习");
}
}
然后在创建一个 Advice 类 代码如下:
public class Advice {
/**
* 用作前置通知
*/
public void beforeStudy(){
System.out.println("学习之前先吃点东西");
}
/**
* 用作后置通知
*/
public void afterStudy(){
System.out.println("学习之后休息一会儿");
}
}
然后我们先使用第一种配置方式----xml 配置
<!--aop配置-->
<aop:config>
<!-- 定义切点 -->
<aop:pointcut expression="execution(* studyAOP.Study.study(..))"
id="pointcut" />
<!-- 定义切面 -->
<aop:aspect ref="advice">
<!-- 前置通知 pointcut-ref="pointcut" 这里 的 pointcut 就是上面 定义的切点 的 id-->
<aop:before pointcut-ref="pointcut" method="beforeStudy" />
<!--beforeStudy 运行在 pointcut 前面-->
<!-- 后置通知 -->
<aop:after method="afterStudy" pointcut-ref="pointcut"/>
<!--beforeStudy 运行在 pointcut 后面-->
</aop:aspect>
</aop:config>
以上就是xml 的配置了 很简单,就是 初始化bean 对象 然后 用 aop:config 标签 定义配置 ,里面 aop:pointcut 声明切点, aop:aspect 声明切面 最后定义通知就行了
然后 我们再写个测试类 测试
public class test {
public static void main(String[] args) {
// 获取 context 容器对象
ApplicationContext context=
new ClassPathXmlApplicationContext("applicationContext2.xml");
//从 context 容器中获取 bean
Study studybean = (Study)context.getBean("study");//获取Study
// 调用 studybean 中的 study 方法
studybean.study();
}
}
运行结果如图,由于我们在xml 中已经配置好了,所以 在 studybean.study(); 执行的时候,spring框架中的 aop 机制会 自动拦截此方法
接下来给大家说第二种-----通过注解的方式配置aop
步骤如下:
- 我们先 注释掉 xml 中的配置
2.然后在xml 中开启 注解扫描,(试想一下,凭什么 spring 能 知道你的这些注解并且自动帮你完成配置呢,首先你得要告诉别人是不是)
所以开启注解的代码
<aop:aspectj-autoproxy />
<!--开启aop注解方式,此步骤不能少,这样java类中的aop注解才会生效-->
<context:component-scan base-package="studyAOP" />
<!--开启注解扫描-->
补充说明下, <context:component-scan base-package="(包路径)" /> 这一句无非就是指定扫描的位置 所以如果 你创建的类不再同一包下,只要确保你每个类被扫描到了就行了
- 改造 Study类 代码:
@Component
public class Study {
public void study(){
System.out.println("正在学习");
// return 1/0;
}
}
这里的 @Component 只是通过注解 自动注入容器而已,跟aop 其实没有必然的关系,就算在平时我们为了不想配置 xml 中 这一句
<bean id="study" class="studyAOP.Study"></bean>
我们也可以用,但是要记住 只要是要用注解 就请 打开扫描
<context:component-scan base-package="(包路径)" />
好了回归正题我们继续
4.改造advice 类 代码:
@Aspect //定义为切面
@Component // 把类注入 bean 容器里面
public class Advice {
@Pointcut("execution(* studyAOP.Study.study(..))")
public void pointCut (){}
/**
* 用作前置通知
*/
@Before("pointCut()")
public void beforeStudy(){
System.out.println("学习之前先吃点东西");
}
/**
* 用作后置通知
*/
@After("pointCut()")
public void afterStudy(){
System.out.println("学习之后休息一会儿");
}
}
5 测试类测试(测试类不用改变)
运行结果是一样一样的!
最后补充说明
补充说明每个注释的作用,与xml 对照看
@Aspect 这一句 作用 等同于 xml 中的
<aop:aspect ref="advice"></aop:aspect>
@Component 就不用说了上面已经说过 ,需要注意的就是 Component 注入的bean 默认 id 为 类名但是第一个字母小写
然后就是这两句
@Pointcut("execution(* studyAOP.Study.study(..))")
public void pointCut (){}
等同于xml 中的
<!-- 定义切点 -->
<aop:pointcut expression="execution(* studyAOP.Study.study(..))"
id="pointcut" />
这里的 pointCut 方法其实可以看作是 一个代理对象而已 它的方法名可以任意,相当于
id=“pointcut” (aop:pointcut 标签的id)
然后就是定义通知
@Before("pointCut()")
public void beforeStudy(){
System.out.println("学习之前先吃点东西");
}
这个就简单了
<aop:before pointcut-ref="pointcut" method="beforeStudy" />
一目了然(pointCut 和 pointcut)都是名字而已 其实是等同的
好了,这两种配置就讲完了,祝大家好好学习,天天向上,哈哈!