AOP+代理(2.24)
一、AOP
1.AOP概念:面向切面编程

2.切点:方法
连接点:被切面选中的方法
切面类:补强的方法(可变的部分),可以为多个连接点进行补强
- 前置-->前置通知 Advice
- 后置-->后置通知
3.Aop的用处:
①业务日志:后置通知
②统一异常处理:controller层try catch改为植入的方式
③事务
④鉴权
二、代理
1.概念:

代理 = 代理对象包裹目标对象 + 对目标方法的任意增强(可前置/后置/环绕/异常/替换)
2.分类:
①静态代理:编译期 增强
②动态代理:运行期 增强
- jdk 动态代理 给接口动态增强 不频繁
- cglib 动态代理 给类动态增强 频繁
静态代理:

cglib动态代理:

三、代理实战:
1.静态代理:
项目结构:

Restaurant接口:
public interface Restaurant {
void eatMeet(String meet);
void eatFish(String fish);
}
PeaceRestaurant实现类:
public class PeaceRestaurant implements Restaurant{
@Override
public void eatMeet(String meet) {
System.out.println(meet + "9999 一份");
}
@Override
public void eatFish(String fish) {
System.out.println(fish + "666 一份");
}
}
ProxyRestaurant代理类:
public class ProxyRestaurant implements Restaurant{
private Restaurant restaurant;
public ProxyRestaurant(Restaurant restaurant){
this.restaurant = restaurant;
}
@Override
public void eatMeet(String meet) {
System.out.println("开始点餐");
restaurant.eatMeet(meet);
System.out.println("送你500代金券");
}
@Override
public void eatFish(String fish) {
System.out.println("本地鱼,打八折");
restaurant.eatFish(fish);
}
}
Main:
public class Main {
public static void main(String[] args) {
Restaurant restaurant = new PeaceRestaurant();//多态
restaurant.eatFish("鳕鱼");
System.out.println("--------使用代理---------");
ProxyRestaurant proxy = new ProxyRestaurant(restaurant);
proxy.eatFish("金龙鱼");
}
}
执行结果:
鳕鱼666 一份
--------使用代理---------
本地鱼,打八折
金龙鱼666 一份
2.(1)jdk动态代理:
项目结构:

Restaurant接口:
public interface Restaurant {
void eatMeet(String meet);
void eatFish(String fish);
}
PeaceRestaurant实现类:
public class PeaceRestaurant implements Restaurant {
@Override
public void eatMeet(String meet) {
System.out.println(meet + "9999 一份");
}
@Override
public void eatFish(String fish) {
System.out.println(fish + "666 一份");
}
}
ProxyRestaurantJdk代理类:
public class ProxyRestaurantJdk implements InvocationHandler {
private Object target;
public ProxyRestaurantJdk(Object target){
this.target = target;
}
//代理方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(proxy.getClass());
System.out.println("吃饭前洗手");
//调用目标方法
Object ret = method.invoke(target, args);
System.out.println("吃饭后洗手");
return ret;
}
}
Main:
public class Main {
public static void main(String[] args) {
//PeaceRestautant 目标对象
Restaurant restaurant = new PeaceRestaurant();
restaurant.eatFish("黄花鱼");
System.out.println("--------使用代理---------");
//增强后的代理对象
ProxyRestaurantJdk proxyRestautantJdk = new ProxyRestaurantJdk(restaurant);
//动态生成的目标代理对象, 类的所有方法都被代理
Restaurant restaurant1 = (Restaurant) Proxy.newProxyInstance(
restautant.getClass().getClassLoader(), //相同的类的加载器
restautant.getClass().getInterfaces(), //生成的代理对象,具有相同的接口数组
proxyRestautantJdk //增强的代码逻辑
);
restaurant1.eatFish("金龙鱼");
restaurant1.eatMeet("牛排");
}
}
执行结果:
黄花鱼666 一份
--------使用代理---------
class jdk.proxy1.$Proxy0
吃饭前洗手
金龙鱼666 一份
吃饭后洗手
class jdk.proxy1.$Proxy0
吃饭前洗手
牛排9999 一份
吃饭后洗手
(2)jdk动态代理优化:
main:
public class Main {
public static void main(String[] args) {
Restaurant restaurant = new PeaceRestaurant();
restaurant.eatFish("黄花鱼");
System.out.println("--------使用代理---------");
//ProxyRestaurantJdk proxyRestautantJdk = new ProxyRestaurantJdk(restaurant);
//动态生成的目标代理对象
Restaurant restaurant1 = (Restaurant) Proxy.newProxyInstance(
PeaceRestaurant.class.getClassLoader(), //相同的类的加载器
PeaceRestaurant.class.getInterfaces(), //生成的代理对象,具有相同的接口数组
new ProxyRestaurantJdk(restaurant) //增强的代码逻辑
);
restaurant1.eatFish("金龙鱼");
restaurant1.eatMeet("牛排");
}
}
执行结果:
黄花鱼666 一份
--------使用代理---------
class jdk.proxy1.$Proxy0
吃饭前洗手
金龙鱼666 一份
吃饭后洗手
class jdk.proxy1.$Proxy0
吃饭前洗手
牛排9999 一份
吃饭后洗手
3.cglib动态代理(了解):
项目结构:

PeaceRestaurant类:
public class PeaceRestaurant {
public void eatMeet(String meet) {
System.out.println(meet + "9999 一份");
}
public void eatFish(String fish) {
System.out.println(fish + "666 一份");
}
}
ProxyRestaurantCglib代理类:
public class ProxyRestaurantCglib implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("cglib代理执行前" + method.getName());
//调用目标对象的方法
Object o = proxy.invokeSuper(obj,args);
System.out.println("cglib代理执行后" + method.getName());
return o;
}
}
Main:
public class Main {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(PeaceRestaurant.class);
enhancer.setCallback(new ProxyRestaurantCglib());
PeaceRestaurant restaurant = (PeaceRestaurant)enhancer.create();
restaurant.eatFish("鱼香肉丝");
restaurant.eatMeet("红烧肉");
}
}
执行结果:
cglib代理执行前eatFish
鱼香肉丝666 一份
cglib代理执行后eatFish
cglib代理执行前eatMeet
红烧肉9999 一份
cglib代理执行后eatMeet
四、Aop使用:
controller.CarController:
@RestController
@RequestMapping("/car")
public class CarController {
@Autowired
private CarService carService;
@GetMapping("/all")
public List<Car> listGet() {
List<Car> carList = null;
try{
carList = carService.findAll();
System.out.println("carList:"+carList);
}catch (Exception e) {
throw new RuntimeException(e);
}
return carList;
}
}
aop.TimeAspect:
@Component
@Aspect //当前类是个切面
public class TimeAspect {
//1 切点逻辑 哪些类的哪些方法
//execution([访问修饰符] 返回值类型 包名.类名.方法名(参数类型) [异常])
// 任意返回值类型 包名.类名.方法名
@Pointcut("execution(* cn.wolfcode.controller.*.*(..))")
public void pointcut(){}
//2 通知方法 Around 表示通知方式
@Around("pointcut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
Object result = pjp.proceed(); //目标方法调用
long end = System.currentTimeMillis();
System.out.println("耗时:" + (end-start) + "ms");
return result;
}
}
BoosApplicationTests:
@SpringBootTest
class BoosApplicationTests {
@Autowired
private CarController carController;
@Autowired
private DepartmentController departmentController;
@Test
void contextLoads() {
List<Car> carList = carController.listGet();
departmentController.listGet(new HashMap<>());
}
}
执行结果:
carList:[Car(id=1, name=Tesla Model 3, color=红色), Car(id=2, name=BMW 5 Series, color=黑色), Car(id=3, name=Toyota Camry, color=白色), Car(id=4, name=Audi A4, color=银色)]
耗时:237ms
耗时:47ms
浙公网安备 33010602011771号