2021-07-24 SpringAOP
小小的疑惑,我还是不懂啊。代理模式,切面,切入点
AOP面向切面编程
代理模式
代理模式就是SpringAOP的底层。
代理模式的分类:
- 静态代理
- 动态代理
静态代理
角色分析:
- 抽象角色:一般使用接口或抽象类
- 真实角色:被代理的角色
- 代理角色:代理真实角色,会做一些附属操作
- 客户:访问代理对象的人
代理模式的好处:
- 可以使真实角色的操作更加纯粹
- 公共业务交给了代理角色,实现类业务的分工
- 公共业务发生扩展的时候,方便集中管理
缺点:
- 之歌真实角色就会产生一个代理角色;代码量翻倍
代码分析1
-
接口
package com.klaus.demo01; //租房 public interface Rent { public void rent(); }
-
真实角色
package com.klaus.demo01; //房东 public class Host implements Rent{ @Override public void rent() { System.out.println("房东出租房"); } }
-
代理角色
package com.klaus.demo01; public class Proxy implements Rent{ private Host host; public Proxy() { } public Proxy(Host host) { this.host = host; } @Override public void rent() { seeHouse(); host.rent(); contract(); charge(); } public void seeHouse(){ System.out.println("中介带你看房子"); } public void charge(){ System.out.println("收中介费"); } public void contract(){ System.out.println("签订租赁合同"); } }
-
客户类
package com.klaus.demo01; public class Client { public static void main(String[] args) { // 房东要出租房子 Host host = new Host(); // 代理,中介帮房东租房,但中介一般会多一些附属操作 Proxy proxy = new Proxy(host); // 客户不同面对房东,直接找中介租房即可 proxy.rent(); } }
代码分析2
服务类原本只进行增删改查的业务,这时候是不需要代理的。但如果增加需求:每次执行操作时增加日志,直接在真实角色上修改代码不是很妥善,所以用到了代理,代理还是调用原来角色的方法,但是新增了打印日志的方法并且没有改动原代码。
-
接口类
package com.klaus.demo02; public interface UserService { public void add(); public void delete(); public void update(); public void query(); }
-
真实角色
package com.klaus.demo02; public class UserServiceImpl implements UserService{ @Override public void add() { System.out.println("增加了一个对象"); } @Override public void delete() { System.out.println("删除了一个对象"); } @Override public void update() { System.out.println("修改了一个对象"); } @Override public void query() { System.out.println("查询了一个对象"); } }
-
代理角色
package com.klaus.demo02; // 代理模式要有一个真实客户 public class UserServiceProxy implements UserService{ UserServiceImpl userService; public void setUserService(UserServiceImpl userService) { this.userService = userService; } @Override public void add() { userService.add(); log("add"); } @Override public void delete() { userService.delete(); log("delete"); } @Override public void update() { userService.update(); log("update"); } @Override public void query() { userService.query(); log("query"); } // 日志方法 public void log(String msg){ System.out.println("使用了" + msg + "方法"); } }
-
客户类
package com.klaus.demo02; public class Client { public static void main(String[] args) { UserServiceImpl userService = new UserServiceImpl(); UserServiceProxy userServiceProxy = new UserServiceProxy(); userServiceProxy.setUserService(userService); userServiceProxy.delete(); } }
动态代理(on 反射)
- 动态代理和静态代理角色一样
- 动态代理的代理类是动态生成的,不像静态类要自己写
- 动态代理分两类:
- 基于接口的动态代理 — JDK动态代理
- 基于类的动态代理 ----- cglib
- 还有java 字节码:javasist
ProxyInvocationHandler 和 Proxy
AOP实现
一、使用Spring的API
-
UserService.java
package com.klaus.service; public interface UserService { public void add(); public void delete(); public void update(); public void query(); }
-
UserServiceImpl.java
package com.klaus.service; public class UserServiceImpl implements UserService{ @Override public void add() { System.out.println("add user"); } @Override public void delete() { System.out.println("delete user"); } @Override public void update() { System.out.println("update user"); } @Override public void query() { System.out.println("query user"); } }
-
Log.java
package com.klaus.log; import org.springframework.aop.MethodBeforeAdvice; import java.lang.reflect.Method; public class Log implements MethodBeforeAdvice { // method: 要执行对象的方法 // args: 参数 // o: equals target @Override public void before(Method method, Object[] args, Object o) { System.out.println(o.getClass().getName()+ "的" + method.getName() + "被执行"); } }
-
AfterLog.java
package com.klaus.log; import org.springframework.aop.AfterAdvice; import org.springframework.aop.AfterReturningAdvice; import java.lang.reflect.Method; public class AfterLog implements AfterReturningAdvice { @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("执行了" + target.getClass().getName()+ "的" + method.getName() + "方法,返回结果为" + returnValue); } }
-
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="userService" class="com.klaus.service.UserServiceImpl" /> <bean id="log" class="com.klaus.log.Log"/> <bean id="afterLog" class="com.klaus.log.AfterLog"/> <!-- 配置AOP --> <aop:config> <!-- 切入点 --> <!--execution()里 返回类型 函数范围 参数 --> <aop:pointcut id="pointcut" expression="execution(* com.klaus.service.UserServiceImpl.*(..))"/> <!-- 执行环绕增强 --> <aop:advisor advice-ref="log" pointcut-ref="pointcut"/> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/> </aop:config> </beans>
-
MyTest.java
import com.klaus.service.UserService; import com.klaus.service.UserServiceImpl; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = (UserService) context.getBean("userService"); userService.add(); } }
-
执行结果
com.klaus.service.UserServiceImpl的add被执行 add user 执行了com.klaus.service.UserServiceImpl的add方法,返回结果为null
二、自定义实现AOP
三、使用注解实现
本文来自博客园,作者:klaus08,转载请注明原文链接:https://www.cnblogs.com/klaus08/p/15104980.html