AOP:面向切面、面向方面、面向接口是一种横切技术
横切技术运用:
1.事务管理: (1)数据库事务:(2)编程事务(3)声明事物:Spring AOP-->声明事物
2.日志处理:
3.安全验证: Spring AOP---OOP升级
静态代理原理:目标对象:调用业务逻辑 代理对象:日志管理
表示层调用--->代理对象(日志管理)-->调用目标对象
动态代理原理:spring AOP采用动态代理来实现
(1)实现InvocationHandler接口
(2)创建代理类(通过java API)
Proxy.newProxyInstance(动态加载代理类,代理类实现接口,使用handler);
(3)调用invoke方法(虚拟机自动调用方法)
日志处理
//调用目标对象
method.invoke("目标对象","参数");
日志处理
通过代理对象--(请求信息)-->目标对象---(返回信息)----> 代理对象
Spring 动态代理中的基本概念
1、关注点(concern)
一个关注点可以是一个特定的问题,概念、或者应用程序的兴趣点。总而言之,应用程序必须达到一个目标
安全验证、日志记录、事务管理都是一个关注点
在oo应用程序中,关注点可能已经被代码模块化了还可能散落在整个对象模型中
2、横切关注点(crosscutting concern)
如何一个关注点的实现代码散落在多个类中或方法中
3、方面(aspect)
一个方面是对一个横切关注点模块化,它将那些原本散落在各处的,
用于实现这个关注点的代码规整在一处
4、建议(advice)通知
advice是point cut执行代码,是方面执行的具体实现
5、切入点(pointcut)
用于指定某个建议用到何处
6、织入(weaving)
将aspect(方面)运用到目标对象的过程
7、连接点(join point)
程序执行过程中的一个点
通知类型:
try{
//前置通知
//环绕通知
//调用目标对象方法
//环绕通知
//后置通知
}catch(){
//异常通知
}finally{
//终止通知
}
流程图
一.静态代理原理实例:
项目结构图:
IUserServ接口代码
- public interface IUserServ {
- List<User> findAllUser();
- int deleteUserById(User user);
- int saveUser(User user);
- }
public interface IUserServ { List<User> findAllUser(); int deleteUserById(User user); int saveUser(User user); }
UserServImpl实现类代码
- public class UserServImpl implements IUserServ {
- public int deleteUserById(User user) {
- System.out.println("******执行删除方法******");
- return 0;
- }
- public List<User> findAllUser() {
- System.out.println("*******执行查询方法*******");
- return null;
- }
- public int saveUser(User user) {
- System.out.println("*******执行添加方法********");
- return 0;
- }
- }
public class UserServImpl implements IUserServ { public int deleteUserById(User user) { System.out.println("******执行删除方法******"); return 0; } public List<User> findAllUser() { System.out.println("*******执行查询方法*******"); return null; } public int saveUser(User user) { System.out.println("*******执行添加方法********"); return 0; } }
UserServProxyImpl实现类代码
- //代理类:完成日志输出
- public class UserServProxyImpl implements IUserServ {
- // 访问目标对象(UserServImpl)
- // 代理对象(UserServProxyImpl)
- // 创建目标对象
- private IUserServ iuserServ ;//= new UserServImpl();
- public UserServProxyImpl(IUserServ iuserServ){
- this.iuserServ = iuserServ;
- }
- public int deleteUserById(User user) {
- beforeLog();
- //调用目标对象里方法
- iuserServ.deleteUserById(user);
- afterLog();
- return 0;
- }
- public List<User> findAllUser() {
- beforeLog();
- //调用目标对象里方法
- iuserServ.findAllUser();
- afterLog();
- return null;
- }
- public int saveUser(User user) {
- beforeLog();
- //调用目标对象里方法
- iuserServ.saveUser(user);
- afterLog();
- return 0;
- }
- private void beforeLog() {
- System.out.println("开始执行");
- }
- private void afterLog() {
- System.out.println("执行完毕");
- }
- }
//代理类:完成日志输出 public class UserServProxyImpl implements IUserServ { // 访问目标对象(UserServImpl) // 代理对象(UserServProxyImpl) // 创建目标对象 private IUserServ iuserServ ;//= new UserServImpl(); public UserServProxyImpl(IUserServ iuserServ){ this.iuserServ = iuserServ; } public int deleteUserById(User user) { beforeLog(); //调用目标对象里方法 iuserServ.deleteUserById(user); afterLog(); return 0; } public List<User> findAllUser() { beforeLog(); //调用目标对象里方法 iuserServ.findAllUser(); afterLog(); return null; } public int saveUser(User user) { beforeLog(); //调用目标对象里方法 iuserServ.saveUser(user); afterLog(); return 0; } private void beforeLog() { System.out.println("开始执行"); } private void afterLog() { System.out.println("执行完毕"); } }
ActionTest测试类代码
- public class ActionTest {
- public static void main(String[] args) {
- //用户访问代理对象---信息->目标对象
- IUserServ iuserServ = new UserServProxyImpl(new UserServImpl());
- iuserServ.findAllUser();
- }
- }
public class ActionTest { public static void main(String[] args) { //用户访问代理对象---信息->目标对象 IUserServ iuserServ = new UserServProxyImpl(new UserServImpl()); iuserServ.findAllUser(); } }
运行结果:
开始执行
*******执行查询方法*******
执行完毕
二.动态代理实例
项目结构图:
IUserServ接口代码与UserServImpl实现类代码和上述代码相同
LogHandler类代码
- public class LogHandler implements InvocationHandler {
- //目标对象
- private Object targetObject;
- /**
- * 创建动态代理类
- * @return object(代理类)
- */
- public Object createProxy(Object targetObject){
- this.targetObject = targetObject;
- return Proxy.newProxyInstance(
- targetObject.getClass().getClassLoader(),
- targetObject.getClass().getInterfaces(), this);
- }
- @Override
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- Object obj = null;
- try {
- beforeLog();
- //obj: 目标对象--->代理对象的返回值--->返回给调用者的信息
- //this.invoke("目标对象","代理对象给目标对象传递参数");
- //调用目标对象中方法
- obj = method.invoke(targetObject, args);
- afterLog();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return obj;
- }
- //日志管理方法
- private void beforeLog(){
- System.out.println("开始执行");
- }
- private void afterLog(){
- System.out.println("执行完毕");
- }
- }
public class LogHandler implements InvocationHandler { //目标对象 private Object targetObject; /** * 创建动态代理类 * @return object(代理类) */ public Object createProxy(Object targetObject){ this.targetObject = targetObject; return Proxy.newProxyInstance( targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object obj = null; try { beforeLog(); //obj: 目标对象--->代理对象的返回值--->返回给调用者的信息 //this.invoke("目标对象","代理对象给目标对象传递参数"); //调用目标对象中方法 obj = method.invoke(targetObject, args); afterLog(); } catch (Exception e) { e.printStackTrace(); } return obj; } //日志管理方法 private void beforeLog(){ System.out.println("开始执行"); } private void afterLog(){ System.out.println("执行完毕"); } }
ActionTest测试类代码:
- public class ActionTest {
- public static void main(String[] args) {
- //创建代理对象iuserServ
- LogHandler handler = new LogHandler();
- IUserServ iuserServ = (IUserServ)handler.createProxy(new UserServImpl());
- iuserServ.deleteUserById(new User());
- }
- }
public class ActionTest { public static void main(String[] args) { //创建代理对象iuserServ LogHandler handler = new LogHandler(); IUserServ iuserServ = (IUserServ)handler.createProxy(new UserServImpl()); iuserServ.deleteUserById(new User()); } }
运行结果:
开始执行
******执行删除方法******
执行完毕
三.Spring AOP使用(2.x版本之前)
项目结构图:
IUserServ接口代码与UserServImpl实现类代码和上述代码相同
配置步骤:
1、配置目标对象(applicationContext.xml)
- <bean id="userServTarget" class="com.tarena.biz.impl.UserServImpl"/>
<bean id="userServTarget" class="com.tarena.biz.impl.UserServImpl"/>
2、配置通知
(a)前置通知(BeforeLogAdvice)
- public class BeforeLogAdvice implements MethodBeforeAdvice {
- /**
- * Method method:调用目标对象的方法
- * Object[] args:发送给目标对象的参数列表
- * Object target:目标对象
- */
- public void before(Method method, Object[] args, Object target)
- throws Throwable {
- beforeLog();
- }
- private void beforeLog(){
- System.out.println("开始执行");
- }
- }
public class BeforeLogAdvice implements MethodBeforeAdvice { /** * Method method:调用目标对象的方法 * Object[] args:发送给目标对象的参数列表 * Object target:目标对象 */ public void before(Method method, Object[] args, Object target) throws Throwable { beforeLog(); } private void beforeLog(){ System.out.println("开始执行"); } }
(b)后置通知(AfterLogAdvice)
- public class AfterLogAdvice implements AfterReturningAdvice {
- /**
- * Object returnValue:目标对象返回值
- * Method method:目标对象方法名
- * Object[] args:目标对象参数列表
- * Object target:目标对象
- */
- public void afterReturning(Object returnValue, Method method,
- Object[] args, Object target) throws Throwable {
- afterLog();
- }
- private void afterLog(){
- System.out.println("执行完毕");
- }
- }
public class AfterLogAdvice implements AfterReturningAdvice { /** * Object returnValue:目标对象返回值 * Method method:目标对象方法名 * Object[] args:目标对象参数列表 * Object target:目标对象 */ public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { afterLog(); } private void afterLog(){ System.out.println("执行完毕"); } }
(c)在spring容器中,让容器管理通知(applicationContext.xml)
- <!-- 定义通知 -->
- <!-- 前置通知 -->
- <bean id="beforeLogAdvice" class="com.tarena.advice.BeforeLogAdvice"/>
- <!-- 后置通知 -->
- <bean id="afterLogAdvice" class="com.tarena.advice.AfterLogAdvice"/>
<!-- 定义通知 --> <!-- 前置通知 --> <bean id="beforeLogAdvice" class="com.tarena.advice.BeforeLogAdvice"/> <!-- 后置通知 --> <bean id="afterLogAdvice" class="com.tarena.advice.AfterLogAdvice"/>
3、配置代理对象(applicationContext.xml)
- <!-- 代理类作用: 生成代理类,织入通知 -->
- <bean id="userServProxy"
- class="org.springframework.aop.framework.ProxyFactoryBean">
- <property name="interfaces">
- <!-- 可以添加多个接口 -->
- <list>
- <value>com.tarena.biz.IUserServ</value>
- </list>
- </property>
- <!-- 引入通知 -->
- <property name="interceptorNames">
- <list>
- <value>beforeLogAdvice</value>
- <value>afterLogAdvice</value>
- </list>
- </property>
- <!-- 目标对象 -->
- <property name="target" ref="userServTarget"/>
- </bean>
<!-- 代理类作用: 生成代理类,织入通知 --> <bean id="userServProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="interfaces"> <!-- 可以添加多个接口 --> <list> <value>com.tarena.biz.IUserServ</value> </list> </property> <!-- 引入通知 --> <property name="interceptorNames"> <list> <value>beforeLogAdvice</value> <value>afterLogAdvice</value> </list> </property> <!-- 目标对象 --> <property name="target" ref="userServTarget"/> </bean>
4.访问()
Spring容器:通过代理对象调用-->织入通知--->目标对象
程序员:访问代理对象
测试类(ActionTest):
- public class ActionTest {
- public static void main(String[] args) {
- ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
- IUserServ iuserServ = (IUserServ)ac.getBean("userServProxy");
- iuserServ.deleteUserById(new User());
- iuserServ.findAllUser();
- }
- }
public class ActionTest { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); IUserServ iuserServ = (IUserServ)ac.getBean("userServProxy"); iuserServ.deleteUserById(new User()); iuserServ.findAllUser(); } }
运行结果:
开始执行
******执行删除方法******
执行完毕
开始执行
*******执行查询方法*******
执行完毕
四.Spring AOP使用(2.x版本之后)这种方式需要额外添加两个jar包,
存放位置在spring-framework-2.5.6.SEC01\lib\aspectj文件夹下。
项目结构图
IUserServ接口代码与UserServImpl实现类代码和上述代码相同
LogAdvice中
- public class LogAdvice {
- public void beforeLog(){
- System.out.println("开始执行");
- }
- public void afterLog(){
- System.out.println("执行完毕");
- }
- }
public class LogAdvice { public void beforeLog(){ System.out.println("开始执行"); } public void afterLog(){ System.out.println("执行完毕"); } }
applicationContext.xml中
- <!-- spring2.x后 -->
- <!-- 目标对象 -->
- <bean id="userServImpl" class="com.tarena.biz.impl.UserServImpl"/>
- <!-- 通知 -->
- <bean id="logAdvice" class="com.tarena.advice.LogAdvice"/>
- <aop:config>
- <aop:aspect id="logAspect" ref="logAdvice">
- <!-- 切入点 -->
- <aop:pointcut id="beforePointCut"
- expression="execution(* saveUser*(..))"/>
- <aop:pointcut id="afterPointCut"
- expression="execution(* saveUser*(..))"/>
- <!-- 织入(通知作用于切入点) -->
- <aop:before method="beforeLog" pointcut-ref="beforePointCut"/>
- <aop:after method="afterLog" pointcut-ref="afterPointCut"/>
- </aop:aspect>
- </aop:config>
<!-- spring2.x后 --> <!-- 目标对象 --> <bean id="userServImpl" class="com.tarena.biz.impl.UserServImpl"/> <!-- 通知 --> <bean id="logAdvice" class="com.tarena.advice.LogAdvice"/> <aop:config> <aop:aspect id="logAspect" ref="logAdvice"> <!-- 切入点 --> <aop:pointcut id="beforePointCut" expression="execution(* saveUser*(..))"/> <aop:pointcut id="afterPointCut" expression="execution(* saveUser*(..))"/> <!-- 织入(通知作用于切入点) --> <aop:before method="beforeLog" pointcut-ref="beforePointCut"/> <aop:after method="afterLog" pointcut-ref="afterPointCut"/> </aop:aspect> </aop:config>
测试类:
- public class ActionTest {
- public static void main(String[] args) {
- ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
- IUserServ iuserServ = (IUserServ)ac.getBean("userServImpl");
- iuserServ.deleteUserById(new User());
- iuserServ.findAllUser();
- iuserServ.saveUser(new User());
- }
- }
public class ActionTest { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); IUserServ iuserServ = (IUserServ)ac.getBean("userServImpl"); iuserServ.deleteUserById(new User()); iuserServ.findAllUser(); iuserServ.saveUser(new User()); } }
运行结果
******执行删除方法******
*******执行查询方法*******
开始执行
*******执行添加方法********
执行完毕
注:如果要在业务层所有的方法前后添加日志文件,则需要更改为以下配置
- <aop:pointcut id="beforePointCut"
- expression="execution(* com.tarena.biz.*.*(..))"/>
- <aop:pointcut id="afterPointCut"
- expression="execution(* com.tarena.biz.*.*(..))"/>
<aop:pointcut id="beforePointCut" expression="execution(* com.tarena.biz.*.*(..))"/> <aop:pointcut id="afterPointCut" expression="execution(* com.tarena.biz.*.*(..))"/>
运行结果:
开始执行
******执行删除方法******
执行完毕
开始执行
*******执行查询方法*******
执行完毕
开始执行
*******执行添加方法********
执行完毕
相关推荐
SpringAOP动态代理 Spring AOP 使用的动态代理主要有两种方式:JDK 动态代理和 CGLIB 代理。 JDK 动态代理:用于代理实现了接口的类。Spring 会使用 java.lang.reflect.Proxy 类来创建代理对象。 CGLIB 代理:用于...
AOP的意思就是面向切面编程。本文主要是通过梳理JDK中自带的反射机制,实现 AOP动态代理模式,这也是Spring AOP 的实现原理
spring之AOP(动态代理),包括jdk动态代理和CGLib动态代理
主要对Spring AOP的相关概念和简单的静态代理、动态代理以及常见的几种AOP配置方式做总结学习。主要包括:1. AOP的常见概念 2. 静态代理 3. jdk动态代理 4. Aspectj and Aspectjweaver 5. **aop-config** 6. CGLIB ...
Spring AOP 的本质其实就是实现了动态代理,这个和Aspectj不一样,AspectJ 是直接修改你的字节码 完成的 代理模式其实很简单 主要包括 接口+真实的实现类+代理类 在真实类的实例化的时候 使用代理类,所以需要 ...
springAOP配置实现动态代理,有利于熟悉动态代理原理,深入了解spring。
介绍了springAop默认代理方式
NULL 博文链接:https://jadeluo.iteye.com/blog/1940019
死磕Spring之AOP篇 - Spring AOP两种代理对象的拦截处理(csdn)————程序
通过动态代理模拟Spring AOP,通过动态代理模拟Spring AOP
反射实现 AOP 动态代理模式(Spring AOP 的实现 原理)
描述一下Spring AOP? 在Spring AOP中关注点(concern)和横切关注点(cross-cutting ...Spring AOP 代理是什么? 引介(Introduction)是什么? 连接点(Joint Point)和切入点(Point Cut)是什么? 织入(Weaving)是什么?
AOP动态代理描述了Spring AOP中使用Java高级技术功能实现的动态代理,为Spring IOC等高级开发实现了逻辑功能;
NULL 博文链接:https://arne3166.iteye.com/blog/1046340
代理模式与动态代理--Spring AOP原理.doc
Spring-AOP-利用java中的动态代理和Spring的拦截器做到AOP
SpringAOP之探秘(动态代理、责任链模式、注解使用)- 详情:https://blog.csdn.net/Dream_Weave/article/details/85008674
Spring AOP代理详细介绍 前言: 一开始我对spring AOP还是属于一知半解的状态,这几天遇到一个问题,加上又查看了一些Spring相关知识,感觉对这个问题有了更深刻的认识。所以写下来分享一下。 我们知道,Spring支持...
Spring AOP的实现机制中文版,动态代理及原理,自定义类加载器
Spring AOP多种代理机制相关核心类介绍先介绍一些Spring Aop中一些核心类,大致分为三类: advisorCreator ,从spring ioc的扩展接口beanPostProcessor继承,主要用作扫描获取advisor。 advisor :顾问的意思,封装...