| |
|
|
开发:
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图书馆 购物 三丰科技 阅读网 日历 万年历 2025年11日历 | -2025/11/27 23:27:44- |
|
| 网站联系: qq:121756557 email:121756557@qq.com IT数码 |