课堂练习
1、增加拯救少女任务类与拯救少女骑士类
代码如下:
package net.lhf.spring.lesson05.aop_xml;
import org.springframework.stereotype.Component;
/**
* 功能:救美任务类
* 作者:李红芙
* 日期:2021年03月24日
*/
@Component
public class RescueDamselQuest {
public void embark() {
System.out.println("执行救美任务。");
}
}
代码如下:
package net.lhf.spring.lesson05.aop_xml;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 功能:救美骑士类
* 作者:李红芙
* 日期:2021年03月24日
*/
@Component
public class DamselRescuingKnight {
@Autowired
private RescueDamselQuest rescueDamselQuest;
public void embarkOnQuest() {
rescueDamselQuest.embark();
}
}
在测试代码中创建testDamselRescuingKnight()方法。
代码如下:
package net.lhf.spring.lesson05.aop_xml;
import net.lhf.spring.lesson05.aop_xml.BraveKnight;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* 功能:测试骑士类
* 作者:李红芙
* 日期:2021年03月24日
*/
public class TestKnight {
private ClassPathXmlApplicationContext context;
@Before
public void init() {
// 基于Spring配置文件创建应用容器
context = new ClassPathXmlApplicationContext("aop_xml/spring-config.xml");
}
@Test
public void testBraveKnight() {
// 根据名称从应用容器里获取勇敢骑士对象
BraveKnight braveKnight = (BraveKnight) context.getBean("Mike");
// 勇敢骑士执行任务
braveKnight.embarkOnQuest();
}
@Test
public void testDamselRescuingKnight(){
//根据救美骑士类从应用容器里获取救美骑士对象
net.lhf.spring.lesson05.aop_xml.DamselRescuingKnight
damselRescuingKnight =context.getBean(DamselRescuingKnight.class);
damselRescuingKnight.embarkOnQuest();
}
@After
public void destroy() {
// 关闭应用容器
context.close();
}
}
运行testDamselRescuingKnight(),结果:
创建aop_annotation子包,把aop_xml子包中的文件复制到aop_annotation子包中
在aop_annotation子包创建注解接口-Action
代码如下:
package net.lhf.spring.lesson05.aop_annotation;
import java.lang.annotation.*;
/**
* 功能:动作注解接口
* 作者:李红芙
* 日期:2021年3月29日
*/
@Target(ElementType.METHOD)//拦截目标 -方法
@Retention(RetentionPolicy.RUNTIME) //保持策略 -运行时
@Documented//注释文档
public @interface Action {
String name();
}
创建游吟诗人类MinstreAspect
代码如下:
package net.lhf.spring.lesson05.aop_annotation;
import org.aspectj.lang.JoinPoint;
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;
/**
* 功能:游吟诗人切面
* 作者:李红芙
* 日期:2021年3月29日
*/
@Aspect
@Component//交给Spring容器管理
public class MinstrelAspect {
//注解声明切点
@Pointcut("execution(* net.lhf.spring.lesson05..*.embarkOnQuest(..))")
public void embark() {
}
//注解声明前置通知
@Before("embark()")
public void singBeforeQuest(JoinPoint joinPoint){
System.out.println("啦啦啦,骑士出发啦!");
}
//注解声明后置通知
@After("embark()")
public void singAfterQuest(JoinPoint joinPoint){
System.out.println("真棒啊,骑士完成了任务!");
}
}
在aop_annotation子包里创建Spring配置类 - AopConfig
代码如下:
package net.lhf.spring.lesson05.aop_annotation;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/**
* 功能:AOP配置类
* 作者:李红芙
* 日期:2021年03月29日
*/
@Configuration // 标明是Spring配置类
@ComponentScan("net.lhf.spring.lesson05.aop_annotation") // 组件扫描
@EnableAspectJAutoProxy // 开启Spring对ApectJ的支持
public class AopConfig {
}
在aop_annotation子包里创建测试类 - TestKnight
代码如下:
package net.lhf.spring.lesson05.aop_annotation;
import net.lhf.spring.lesson05.aop_xml.BraveKnight;
import net.lhf.spring.lesson05.aop_xml.DamselRescuingKnight;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* 功能:测试骑士类
* 作者:李红芙
* 日期:2021年03月29日
*/
public class TestKnight {
private ClassPathXmlApplicationContext context;
@Before
public void init() {
// 基于Spring配置文件创建应用容器
context = new ClassPathXmlApplicationContext("aop_xml/spring-config.xml");
}
@Test
public void testBraveKnight() {
// 根据名称从应用容器里获取勇敢骑士对象
net.lhf.spring.lesson05.aop_xml.BraveKnight braveKnight = (BraveKnight) context.getBean("Mike");
// 勇敢骑士执行任务
braveKnight.embarkOnQuest();
}
@Test
public void testDamselRescuingKnight(){
//根据救美骑士类从应用容器里获取救美骑士对象
net.lhf.spring.lesson05.aop_xml.DamselRescuingKnight
damselRescuingKnight =context.getBean(DamselRescuingKnight.class);
damselRescuingKnight.embarkOnQuest();
}
@After
public void destroy() {
// 关闭应用容器
context.close();
}
}
运行测试方法testBraveKnight(),查看效果
在按照老师来做的时候,代码出现错误,获取不到Mike
书写错误:把大写的M写成小写的m了,所以获取不到它。
代码如下:
package net.lhf.spring.lesson05.aop_annotation;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* 功能:测试骑士类
* 作者:李红芙
* 日期:2021年03月29日
*/
public class TestKnight {
private AnnotationConfigApplicationContext context;
@Before
public void init() {
// 基于Spring配置类创建应用容器
context = new AnnotationConfigApplicationContext(AopConfig.class);
}
@Test
public void testBraveKnight() {
// 根据名称从应用容器里获取勇敢骑士对象
BraveKnight braveKnight = (BraveKnight) context.getBean("Mike");
// 勇敢骑士执行任务
braveKnight.embarkOnQuest();
}
@Test
public void testDamselRescuingKnight(){
//根据名称从应用容器里获取救美骑士对象
DamselRescuingKnight knight = (DamselRescuingKnight) context.getBean("damselRescuingKnight");
//救美骑士执行任务
knight.embarkOnQuest();
}
@After
public void destroy() {
// 关闭应用容器
context.close();
}
}
在测试程序里增加对拯救少女骑士的测试方法 - testDamselRescuingKnight(),运行结果
实现注解式拦截
(1)修改勇敢骑士类,给embarkOnQuest()添加自定义注解Action
,并设置其name属性。
修改游吟诗人切面类 - MinstrelAspect
代码如下:
package net.lhf.spring.lesson05.aop_annotation;
import org.aspectj.lang.JoinPoint;
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.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* 功能:游吟诗人切面
* 作者:李红芙
* 日期:2021年03月29日
*/
@Aspect // 声明切面
@Component // 声明为Spring管理的Bean
public class MinstrelAspect {
// 注解声明切点(拦截添加了Action注解的方法)
@Pointcut("@annotation(net.lhf.spring.lesson05.aop_annotation.Action)")
public void embark() {
}
// 注解声明前置通知
@Before("embark()")
public void singBeforeQuest(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
Action action = method.getAnnotation(Action.class);
System.out.println(action.name() + "拦截了" + method.getName() + "方法。");
System.out.println("啦啦啦,骑士出发了!");
}
// 注解声明后置通知
@After("embark()")
public void singAfterQuest(JoinPoint joinPoint) {
System.out.println("真棒啊!骑士完成了任务!");
}
}
(3)运行测试方法testBraveKnight(),查看效果
修改拯救少女骑士类,给embarkOnQuest()添加自定义注解Action
(5)运行测试方法testDamselRescuingKnight(),查看效果