切点表达式:
自定义注解annotation:
在新建java类中选择Annotation,并创建对象。
package com.syx.aop.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAspect {
}
@Target后边的是作用域的范围,说明了后边是作用在方法上的。@Retention是作用的生命周期,(RUNTIME)是运行时。
但是这时候的注解并没有任何逻辑我们给他填上逻辑。
package com.syx.aop.aspect;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Component
@Slf4j
@Aspect
public class MyAspectDemo {
//切点作用域
@Around("@annotation(com.syx.aop.config.MyAspect)")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("do before........");
Object proceed = joinPoint.proceed();
log.info("do after..........");
return proceed;
}
}
在这里我们定义了一个切面类,通过@Around("@annotation(com.syx.aop.config.MyAspect)")来声明该切面类的作用范围。
这样就能通过加在方法上面自定义注解。
这样写就是对所有的RequestMapping生效。只要使用RequestMapping注解的全部都生效
面试题:SpringAop的实现方式:
- 代理模式(比较原始不做过多阐述)。
- 使用SpringApi模式(xml配置后来进化成注解)。<aop:config>,配置方法
- 自定义类的方式(也是xml)<aop:config>,配置切面类
- 基于@Aspect注解{1.基于execution表达式}{2.基于自定义注解@Annotation注解表达式}
现在由于spring优化我们可以直接导入一个依赖就可以了。
面试题:SpringAop原理:
代理模式:
模式:适配器门面代理,单例工厂
springAop的底层原理就是基于代理模式。
原本是 调用方直接调用,但是这时候调用方先调用代理对象,代理对象调用目标对象。
一个简单的例子:
package com.syx.aop.aspect;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Component
@Slf4j
@Aspect
public class MyAspectDemo {
//切点作用域
@Around("@annotation(com.syx.aop.config.MyAspect)")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("do before........666");
Object proceed = joinPoint.proceed();
log.info("do after..........666");
return proceed;
}
}
package com.syx.aop.Controller;
import com.syx.aop.config.MyAspect;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping("test")
public class TestController {
@RequestMapping("doBefore")
@MyAspect
public String t1(){
log.info("这是一个t1");
return "t1";
}
}
如果没有代理模式应该是调用下面这个代码,但是实际上是调用上面的代码,然后通过
Object proceed = joinPoint.proceed();
方法来调用上面的方法。
比如日常租房子,租客要去找中介租房子,中介去找房东要房子,一样的道理。
定义:
适用场景:
- 无法直接调用目标方法
- 目标方法提供功能不够,希望进行功能增强 。
接下来我们讲代理的两种方法,不用掌握代码,了解就行。
静态代理:
动态代理:springaop实现了动态代理
- Jdk代理:只能代理接口。
- CGLIB代理 (实现方式):既可以代理类,也可以代理接口
在程序运行时,运用反射机制动态创建而成。代理对象通过invoke方法调用目标对象的方法。并且在里边进行功能增强。
适配器模式是代码的补偿,而代理模式则是刚开始就设计好的。
spring是基于动态代理实现的,动态代理是基于反射实现的。
既可以代理类,又可以代理接口。
jdk和cglib区别:
- jdk可以代理接口不可以代理类,cglib可以代理接口又代理类。
- spring既使用jdk和cglib代理.
八股文:spring什么时候使用jdk代理什么时候实现cglib代理。
spring默认使用jdk代理,默认proxytargetclass是false,如果是接口使用jdk,springboot默认是true,全部使用cglib实现。
面试题:
- 什么是aop
- springaop实现方式:
- 实现原理(jdk,cglib)。
- spring使用哪种jdk,cglib,不太一样springboot 和spring
- jdk和cglib区别:
举例:我要在某ke上面买一个房子,静态代理就是别墅在挂牌出售的时候就已经准备好代理了,不管是谁想买房子,都是这个代理人已经分配好了,动态代理就是我点击买房的时候才会分配好代理。
反射回顾:
任何一个类都可以知道他的所有属性和方法