前文:Spring学习记录(上)
为什么要学习代理模式?因为Spring底层中随处可见
【SpringAOP】和【SpringMVC】面试必问
两种代理模式:
角色分析:
代码步骤:
接口
public interface UserService {void addUser();void deleteUser();void updateUser();void selectUser();
}
真实角色
public class UserServiceImpl implements UserService{@Overridepublic void addUser() {System.out.println("新增了一个用户");}@Overridepublic void deleteUser() {System.out.println("删除了一个用户");}@Overridepublic void updateUser() {System.out.println("修改了一个用户");}@Overridepublic void selectUser() {System.out.println("查找了一个用户");}
}
代理角色
public class UserServiceProxy implements UserService{UserService userService;public void setUserService(UserService userService) {this.userService = userService;}@Overridepublic void addUser() {log("add");userService.addUser();}@Overridepublic void deleteUser() {log("delete");userService.deleteUser();}@Overridepublic void updateUser() {log("update");userService.updateUser();}@Overridepublic void selectUser() {log("select");userService.selectUser();}//新增的业务private 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.addUser();}
}
代理模式的好处:
缺点:
需要了解两个类:Proxy:代理,InvocationHandler:调用处理程序
动态生成代理类的处理程序:
public class ProxyInvocationHandler implements InvocationHandler {//被代理的接口private Object target;public void setTarget(Object target) {this.target = target;}//生成得到代理类public Object getProxy() {Class().getClassLoader(), Class().getInterfaces(), this);}//处理代理实例,并返回结果@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//例子Name());//动态代理本质上是使用反射机制实现return method.invoke(target, args);}//例子private void log(String msg) {System.out.println("[Debug] " + msg);}
}
使用:
public static void main(String[] args) {//真实对象UserServiceImpl userService=new UserServiceImpl();//通过代理处理程序生成ProxyInvocationHandler pih=new ProxyInvocationHandler();//1.设置要代理的对象pih.setTarget(userService);//2.动态生成代理类UserService proxy = (UserService) Proxy();proxy.deleteUser();}
动态代理的好处:
AOP(Aspect Oriented Programming),意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
AOP可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting),在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
AOP技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
作者:Tiffany_弥弥
链接:
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Maven
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.7</version><scope>runtime</scope>
</dependency>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xmlns:aop=""xsi:schemaLocation="://www.springframework/schema/beans/spring-beans.xsd://www.springframework/schema/aop/spring-aop.xsd
"><bean id="userService" class="com.zhanc.service.UserServiceImpl"/><bean id="log" class="com.zhanc.log.Log"/><bean id="afterLog" class="com.zhanc.log.AfterLog"/><!--方式一:使用原生Spring API接口--><!--配置aop--><aop:config><!--切入点:expression:表达式,excution(要执行的位置! *(修饰词) *(返回值) *(列名) *(方法名) *(参数))--><aop:pointcut id="pt1" expression="execution(* com.zhanc.service.UserServiceImpl.*(..))"/><!--执行环绕增加--><aop:advisor advice-ref="log" pointcut-ref="pt1"/><aop:advisor advice-ref="afterLog" pointcut-ref="pt1"/></aop:config></beans>
自定义类:
public class DiyPointCut {public void before(){System.out.println("==========执行前");}public void after(){System.out.println("==========执行后");}
}
...
<bean id="diyPointCut" class="com.zhanc.diy.DiyPointCut"/>
<!--方式二:使用自定义类-->
<aop:config><aop:pointcut id="pt1" expression="execution(* com.zhanc.service.UserServiceImpl.*(..))"/><!--自定义切面,ref-要引用的自定义类--><aop:aspect ref="diyPointCut"><aop:before method="before" pointcut-ref="pt1"/><aop:after method="after" pointcut-ref="pt1"/></aop:aspect>
</aop:config>
...
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xmlns:aop=""xmlns:context=""xsi:schemaLocation="://www.springframework/schema/beans/spring-beans.xsd://www.springframework/schema/aop/spring-aop.xsd://www.springframework/schema/context/spring-context.xsd"><!--指定要扫描的包,这个包下的注解就会生效--><context:component-scan base-package="com.zhanc"/><!--开启注解支持--><context:annotation-config/><aop:aspectj-autoproxy/>...
</beans>
自定义注解切点类:
@Component
@Aspect
public class AnnotationPointCut {@Before("execution(* com.zhanc.service.UserServiceImpl.*(..))")public void before(){System.out.println("----------方法前");}@After("execution(* com.zhanc.service.UserServiceImpl.*(..))")public void after(){System.out.println("----------方法后");}
}
本文发布于:2024-02-02 13:04:30,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170685027143988.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |