全文来自于https://itbaima.net/document
spring spel(了解)
- 很强的一个表达式 有空可以看看,可以搭配外部属性注入
源于spring框架 - 文档地址
https://docs.spring.io/spring-framework/reference/core/expressions/language-ref/literal.html - 使用方法
- 操作字符串
Expression exp = parser.parseExpression("'Hello World'.toUpperCase()"); //调用String的toUpperCase方法
System.out.println(exp.getValue()); //操作字符串
- 数学计算
Expression exp2 = parser.parseExpression("99 + 99 * 3"); //算数运算
System.out.println(exp2.getValue());//数学计算
-xml中使用
<bean id="numberGuess" class="org.spring.samples.NumberGuess">
<property name="randomNumber" value="#{ T(java.lang.Math).random() * 100.0 }"/>
</bean>
外部属性注入
使用方式
- properties文件
- 配置要注入的值
resources/application.properties
test.name=hello
test.age=12
- @Component类
- 这个类注入值 properties的值
@Component
public class Student {
@Value("${test.name}") //这里需要在外层套上 ${ }
private String name; //String会被自动赋值为配置文件中对应属性的值
//构造方法中的参数除了被自动注入外,我们也可以选择使用@Value进行注入
public Student(@Value("${test.name}") String name){
this.name = name;
}
}
- @Configuration类
- 这个类扫描bean 且要扫描properties文件
@Configuration
@ComponentScan("com.test.bean")
@PropertySource("classpath:test.properties") //注意,类路径下的文件名称需要在前面加上classpath:
public class MainConfiguration{
}
AOP 切面编程
概念
- 有很多种AOP,不仅仅是前切,后切,环绕切
- 切面表达式
- 主要看execution表达式看懂即可,到时候拿chatgpt写去
- 直接看这个https://blog.csdn.net/weixin_43793874/article/details/124753521?spm=1001.2014.3001.5506
- 主要学习的
execution
填写格式如下:
修饰符 包名.类名.方法名称(方法参数)
- 修饰符:public、protected、private、包括返回值类型、static等等(使用*代表任意修饰符)
- 包名:如com.test(* 代表全部,比如com.*代表com包下的全部包)
- 类名:使用*也可以代表包下的所有类
- 方法名称:可以使用*代表全部方法
- 方法参数:填写对应的参数即可,比如(String, String),也可以使用*来代表任意一个参数,使用…代表所有参数。
<aop:pointcut id="test" expression="execution(* org.example.entity.Student.study())"/>
1. xml进行切面
- xml文件解释
<bean class="org.example.bean5.Student"/>
:被切的类<bean id="studentAOP" class="org.example.bean5.StudentAOP"/>
:切的类<aop:pointcut id="test" expression="execution(* org.example.bean5.Student.study())"/>
被切的方法,用切面表达式定位<aop:aspect ref="studentAOP">
ref指向切的类<aop:after method="afterStudy" pointcut-ref="test"/>
- after 是在方法执行后切
- afterStudy是AOP切面类中的方法
- pointcut-ref指向被切的方法的id
- xml格式
<bean class="org.example.bean5.Student"/>
<bean id="studentAOP" class="org.example.bean5.StudentAOP"/>
<aop:config>
<aop:pointcut id="test" expression="execution(* org.example.bean5.Student.study())"/>
<aop:pointcut id="test2" expression="execution(* org.example.bean5.Student.study2(String))"/>
<aop:pointcut id="test3" expression="execution(* org.example.bean5.Student.study3(String))"/>
<aop:aspect ref="studentAOP">
<aop:after method="afterStudy" pointcut-ref="test"/>
</aop:aspect>
<aop:aspect ref="studentAOP">
<aop:after method="afterStudy2" pointcut-ref="test2"/>
</aop:aspect>
<aop:aspect ref="studentAOP">
<aop:around method="around" pointcut-ref="test3"/>
</aop:aspect>
</aop:config>
- 切面类解释
JointPoint
:连接点,就是被切的方法 可以拿到很多需要的信息 比如参数
前切
,后切
都用这个
ProceedingJoinPoint
:效果和JointPoint一样,但是这个可以控制返回值环绕切
用这个
public class StudentAOP {
//这个方法就是我们打算对其进行的增强操作
public void afterStudy() {
System.out.println("为什么毕业了他们都继承家产,我还倒给他们打工,我努力的意义在哪里...");
}
// 这个JointPoint来自于AspectJ,
public void afterStudy2(JoinPoint point){
//这个str参数我们该从哪里拿呢?
System.out.println("拿到的参数是:"+point.getArgs()[0]);
}
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("添加的方法");
// 这里的返回值类型虽然是Object,但是实际上你需要人为控制的 你要知道切入的是什么返回值
Object value = joinPoint.proceed(new Object[]{"Rust"});
System.out.println("添加的方法");
return value;
}
}
- 被切类
public class Student {
public void study(){
System.out.println("室友还在打游戏,我狠狠的学Java,太爽了");
//现在我们希望在这个方法执行完之后,打印一些其他的内容,在不修改原有代码的情况下,该怎么做呢?
}
public void study2(String str){ //现在方法有一个String类型的参数
System.out.println(str);
}
public String study3(String str){
return str;
}
}
2. 接口进行切面
- 接口切面解释
- 通过接口进行切面,通过实现不同的接口,且不同的位置
- 通过xml文件 进行切类和被切类的关联
- 接口切面格式
public class StudentAOP implements MethodBeforeAdvice, AfterReturningAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("通过Advice实现AOP");
}
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("我是方法执行之后的结果,方法返回值为:"+returnValue);
}
}
- 接口切面xml
- 通过
<aop:advisor advice-ref="studentAOP" pointcut-ref="test"/>
进行切类
和被切的方法
关联 <aop:pointcut id="test" expression="execution(* org.example.bean6.Student.study())"/>
:被切的方法切面方法不用配置了
,因为我们已经实现了接口,所以spring会自动识别
<bean id="student" class="org.example.bean6.Student"/>
<bean id="studentAOP" class="org.example.bean6.StudentAOP"/>
<aop:config>
<aop:pointcut id="test" expression="execution(* org.example.bean6.Student.study())"/>
<!-- 这里只需要添加我们刚刚写好的advisor就可以了,注意是Bean的名字 -->
<aop:advisor advice-ref="studentAOP" pointcut-ref="test"/>
</aop:config>
- 被切类
public class Student {
public String study(){
System.out.println("我是学习方法!");
return "lbwnb";
}
}
3. 注解进行切面
- 注解切面解释
- 通过注解进行切面,通过给切类注解
@Aspect
,对不同的位置用不同的注解@After
,@Before
,@Around
… - 给配置类添加
@EnableAspectJAutoProxy
注解 - 给切类添加
@Component
注解
- 通过注解进行切面,通过给切类注解
- 配置类
@EnableAspectJAutoProxy
@ComponentScan("org.example.bean7")
@Configuration
public class MyC {
}
- 切类
@Aspect
@Component
public class StudentAOP {
@Before("execution(* org.example.bean7.Student.study())") //execution写法跟之前一样
public void before(){
System.out.println("我是之前执行的内容!");
}
@Around("execution(* com.test.bean.Student.test(..))")
public Object around(ProceedingJoinPoint point) throws Throwable {
System.out.println("方法执行之前!");
Object val = point.proceed();
System.out.println("方法执行之后!");
return val;
}
}
- 被切类
@Component
public class Student {
public void study(){
System.out.println("我是学习方法!");
}
}