| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> Java知识库 -> 代理模式及AOP整理 -> 正文阅读 |
|
[Java知识库]代理模式及AOP整理 |
代理模式这是SpringAOP的底层! 好处: 1.使真实角色的操作更加纯粹,不用去关注一些公共业务 2.公共业务交给代理角色,实现了业务的分工 3.公共业务发生扩展的时候,方便集中管理 缺点: 一个真实角色就会产生一个代理角色;代码量会翻倍,开发效率会变低(解决办法动态代理 ) ? 代理模式的分类: 1.静态代理 【角色分析】 抽象的角色:一般使用接口或者抽象类来解决 真实角色:被代理的角色 代理角色:代理真实角色,代理后,一般会做一些附属操作 客户:访问代理对象的人! //接口/租房的接口 public interface Rent { ? ?public void rent(); } //真实角色 //房东 public class Host implements Rent { ? ?@Override ? ?public void rent() { ? ? ? ?System.out.println("房东要出租房屋!"); ? } } //代理角色 //代理角色 要 实现方法 public class Proxy implements Rent{ ? ?private Host host; ? ?public Proxy() { ? } ? ?public Proxy(Host host) { ? ? ? ?this.host = host; ? } ? ?@Override ? ?public void rent() { ? ? ? ?host.rent(); ? ? ? ?seeHouse(); ? ? ? ?hetong(); ? ? ? ?fare(); ? } ? ?//看房 ? ?public void seeHouse(){ ? ? ? ?System.out.println("中介可以带你看房"); ? } ? ?//收中介费 ? ?public void fare(){ ? ? ? ?System.out.println("中介要收中介费"); ? } ? ?//签合同 ? ?public void hetong(){ ? ? ? ?System.out.println("中介跟你签合同"); ? } } //客户端访问代理角色 //租客 public class Client { ? ?public static void main(String[] args) { ? ? ? ?//房东要出租房屋 ? ? ? ?Host host = new Host(); ? ? ? ?//代理 帮房东出租房屋 ,代理角色一般会有一些附属操作 ? ? ? ?Proxy proxy = new Proxy(host); ? ? ? ?//直接面向代理租房 ? ? ? ?proxy.rent(); ? } } //例子二 //业务接口 public interface UserService { ? ?public void add(); ? ?public void delete(); ? ?public void update(); ? ?public void query(); } //实现类 真实对象 public class UserServiceImpl implements UserService{ ? ?@Override ? ?public void add() { ? ? ? ?System.out.println("增加了用户"); ? } ? ? ?@Override ? ?public void delete() { ? ? ? ?System.out.println("删除了用户"); ? } ... ? ?//代理对象 增加业务 ? ?public class UserServiceProxy implements UserService{ ? ?UserServiceImpl userService; ? //用set方式实现注入 ? ?public void setUserService(UserServiceImpl userService) { ? ? ? ?this.userService = userService; ? } ? ?@Override ? ?public void add() { ? ? ?log("add"); ? ? ? ?userService.add(); ? } ? ?@Override ? ?public void delete() { ? ? ? ?log("delete"); ? ? ? ?userService.delete(); ? } ? ? ? //增加日志方法 ? ?public void log(String msg){ ? ? ? ?System.out.println("[Debug] 使用了"+msg+"方法"); ? } ? ? ... ? ? ? ?//客户端访问 public class Client { ? ?public static void main(String[] args) { ? ? ? ?UserServiceImpl userService=new UserServiceImpl(); ? ? ? ?UserServiceProxy proxy = new UserServiceProxy(); ? ? ? ?//要代理谁? ? ? ? ?proxy.setUserService(userService); ? ? ? ?proxy.add(); ? } } 2.动态代理(底层都是反射) 动态代理和静态代理角色一致,动态代理的代理类 是动态生成的,不是我们直接写好的! 动态代理分为三大类: 基于接口:【JDK动态代理】 基于类:【cglib】 java字节码实现:【javassist】 两个类: Proxy :代理 提供了创建动态代理类和实例的静态方法 InvocationHandler(反射包下得接口) : 调用处理程序并返回结果 //租房的接口 public interface Rent { ? ?public void rent(); } //房东 真实角色 public class Host implements Rent { ? ?@Override ? ?public void rent() { ? ? ? ?System.out.println("房东要出租房屋!"); ? } } ? //我们用这个类自动生成代理类 InvocationHandler 调用处理程序并返回结果 public class ProxyInvocationHandler implements InvocationHandler { ? ?//被代理的接口 ? ?private Rent rent; ? ? ?public void setRent(Rent rent) { ? ? ? ?this.rent = rent; ? } ? ?//生成得到 代理类 ? ?public Object getProxy(){ ? ? ? ?return Proxy.newProxyInstance(this.getClass().getClassLoader(), ? ? ? ? ? ? ? ?rent.getClass().getInterfaces(), ?this); ? } ? ?//处理代理实例,并返回结果 调用代理类的一些执行方法 ? ?@Override ? ?public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { ? ? ? //执行接口上的方法 ? ? ? ?//动态代理的本质,就是使用反射机制实现 ? ? ? ?seeHouse(); ? ? ? ?Object result = method.invoke(rent, args); ? ? ? ?fare(); ? ? ? ?return result; ? } ? ?public void seeHouse(){ ? ? ? ?System.out.println("中介带看房"); ? } ? ?public void fare(){ ? ? ? ?System.out.println("收中介费"); ? } } ? public class Client { ? ?public static void main(String[] args) { ? ? ? ?//真实角色 ? ? ? ?Host host=new Host(); ? ? ? ?//代理角色 暂时没有 ? ? ? ?ProxyInvocationHandler pih = new ProxyInvocationHandler(); ? ? ? ?//通过调用程序处理角色 来处理我们要调用的接口对象! ? ? ? ?pih.setRent(host); ? ? ? ?//这里的proxy就是动态生成的,我们并没有写 ? ? ? ?Rent proxy = (Rent) pih.getProxy(); ? ? ? ?proxy.rent(); ? ? } } 抽取共性: //我们用这个类自动生成代理类 public class ProxyInvocationHandler implements InvocationHandler { ? ?//被代理的接口 ? ?private Object target; ? ? ?public void setTarget(Object target) { ? ? ? ?this.target = target; ? } ? ?//生成得到 代理类 ? ?public Object getProxy(){ ? ? ? ?return Proxy.newProxyInstance(this.getClass().getClassLoader(), ? ? ? ? ? ? ? ?target.getClass().getInterfaces(), ?this); ? } ? ?//处理代理实例,并返回结果,调用代理类的一些执行方法 ? ?@Override ? ?public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { ? ? ? //执行接口上的方法 ? ? ? ?//动态代理的本质,就是使用反射机制实现 ? ? ? ?log(method.getName()); ? ? ? ?Object result = method.invoke(target, args); ? ? ? ?return result; ? } ? ? ?public void log(String msg){ ? ? ? ?System.out.println("执行了"+msg+"方法"); ? } } //调用 public class Client { ? ?public static void main(String[] args) { ? ? ? ?//真实角色 ? ? ? ?UserServiceImpl userService=new UserServiceImpl(); ? ? ? ?//代理角色 不存在 ? ? ? ?ProxyInvocationHandler pih = new ProxyInvocationHandler(); ? ? ? ?//设置要代理的对象 ? ? ? ?pih.setTarget(userService); ? ? ? ?//动态生成代理类 ? ? ? ?UserService proxy =(UserService) pih.getProxy(); ? ? ? ? ?proxy.add(); ? ? } } 动态代理的好处: 1.使真实角色的操作更加纯粹,不用去关注一些公共业务 2.公共业务交给代理角色,实现了业务的分工 3.公共业务发生扩展的时候,方便集中管理 4.一个动态代理类代理的是一个接口,一般对应一类业务 5.一个动态代理类可以代理多个类,只要是实现了同一个接口即可! AOP
? ? spring实现AOP 需要加织入的依赖 <dependency> ? ? ? ? ? ?<groupId>org.aspectj</groupId> ? ? ? ? ? ?<artifactId>aspectjweaver</artifactId> ? ? ? ? ? ?<version>1.9.4</version> ? ? ? ?</dependency> 方式一:使用Spring的API接口实现AOP 原生api接口 //业务接口 public interface UserService { ? ?public void add(); ? ?public void delete(); ? ?public void update(); ? ?public void select(); } //实现类 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 select() { System.out.println("查询一个用户"); } } //需要增加的内容 //直接使用Spring的API public class Log implements MethodBeforeAdvice { ? ?/* method: 要执行的目标对象的方法 ? ?* args : 参数 ? ?* target:目标对象*/ ? ?@Override ? ?public void before(Method method, Object[] args, Object target) throws Throwable { ? ? ? ?System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了"); ? } } ? public class AfterLog implements AfterReturningAdvice { ? ?//returnValue 返回值 ? ?@Override ? ?public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { ? ? ? ?System.out.println("执行了"+method.getName()+"方法,返回结果为"+returnValue); ? } } ? 用最原始方法配置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 ? ? ? ?https://www.springframework.org/schema/beans/spring-beans.xsd ? ? ? ?http://www.springframework.org/schema/aop ? ? ? ?https://www.springframework.org/schema/aop/spring-aop.xsd"> <!--注册bean--> ? ?<bean id="userService" class="com.xie.service.UserServiceImpl"/> ? ?<bean id="log" class="com.xie.log.Log"/> ? ?<bean id="afterlog" class="com.xie.log.AfterLog"/> <!--方式一:使用原生Spring api接口--> <!--配置aop 导入aop的约束--> <aop:config> <!--切入点 我们在哪执行 expression表达式 execution(要执行的位置! * * * * *)--> ? ?<aop:pointcut id="pointcut" expression="execution(* com.xie.service.UserServiceImpl.*(..))"/> <!--执行环绕增强--> ? ?<aop:advisor advice-ref="log" pointcut-ref="pointcut"/> ? ?<aop:advisor advice-ref="afterlog" pointcut-ref="pointcut"/> </aop:config> </beans> 测试类: public class MyTest { ? ?public static void main(String[] args) { ? ? ? ?ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); ? ? ? ?//动态代理代理的是接口 所以这里不能用实现类! ? ? ? ?UserService userService = context.getBean("userService", UserService.class); ? ? ? ?userService.add(); ? } } |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 10:01:59- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |