Spring AOP:静态代理、动态代理和几种常见的aop配置
来源:互联网 发布:vb中arr是什么意思 编辑:程序博客网 时间:2024/06/06 00:42
本文主要对Spring AOP的相关概念和简单的静态代理、动态代理以及常见的几种AOP配置方式做总结学习。真诚希望大家给予批评和指导。
本文以自己写的一个简单Code为例,主要逻辑结构及说明信息依code中的注释内容为说明,所以可能出现 many codes little explianations.
- AOP的常见概念
- 静态代理
- jdk动态代理
- Aspectj and Aspectjweaver
- aop-config
- CGLIB aop-config
- AOP动态代理配置
- AOP自动识别动态代理配置
1. AOP常见概念
- Cross Cutting Concern :
横切性关注点,补充我们OOP纵向编写的补充,可以理解成遍布在系统的处理流程中的,一种独立的服务。 - Aspect : 对我们上面的Cross Cutting Concern 的一种模块化,也就是将其封装成一个类。
- Advice : 对关注点的具体实现,在切面的某个特定的连接点( Joinpoint )上执行的动作。其含有多种通知类型:
之前、返回之后、抛出之后、环绕通知。具体的可以参考文档。 - Pointcut : 定义了这个Adivce 应用到那些 Joinpoint 上。
- Jointpoint : 是 Advice 在应用程序上的执行点或者时机,对Spring来说,它就是方法调用。
- Weave : 将 Advice 应用到Target Object 上的整个过程叫织入。
- Target Object : Advice应用的对象。
2. 项目结构
3 静态代理和动态代理showing
接口:com.qian.subject.Subject –目标类RealSubject和代理类要实现的接口。
目标类: com.qian.realsubject.RealSubject
静态代理类: com.qian.staticproxy.SubjectStaticProxy
动态代理类: com.qian.dynamicproxy.SubjectDanamicProxy
package com.qian.subject;/** * 实际类RealSubject和代理类要实现的接口; * @author Administrator */public interface Subject { public void addSub(String name, String password); public String findSub(String id);}
package com.qian.realsubject;import com.qian.subject.*;/** * Subject的实现类,并重写方法 * @author Administrator * */public class RealSubject implements Subject { public void addSub(String name, String password) { System.out.println("RealSubject.addSub() "+ name+" "+ password); } public String findSub(String id) { System.out.println("RealSubject.findSub() "+ id); return "realSubject.findSub()"; }}
package com.qian.staticproxy;import com.qian.subject.Subject;public class SubjectStaticProxy implements Subject { //Remark: 拿到实际对象的引用; private Subject realSubject; //这里我们通过构造函数拿到; public SubjectStaticProxy(Subject realSubject){ this.realSubject = realSubject; } public void addSub(String name, String password) { System.out.println("staticProxy do something before realSubject.add()"); //调用实际对象的方法 realSubject.addSub(name, password); } public String findSub(String id) { System.out.println("staticProxy do something before realSubject.findSub()"); return realSubject.findSub(id); }}
package com.qian.danamicproxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class SubjectDanamicProxy implements InvocationHandler { //实际要传入的realSubject; private Object realSubject; public Object getSubjectProxy(Object realSubject){ this.realSubject = realSubject; //都是realSubject的; Object proxy = Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), this); //为了看看这个proxy和invoke(proxy)是否一样 System.out.println("--proxy=Prox.new...() is "+proxy.getClass().getName()); return proxy; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("--proxy in invoke parameters is "+proxy.getClass().getName()); checkInfo(); Object result = method.invoke(realSubject, args); return result; } private void checkInfo(){ System.out.println("Doing some checking things before method invocation"); }}
4 Spring实现AOP的方式之Aspectj注解
Aspectj类:com.qian.springaopaspectj.CheckInfoAspect
xml文件:applicationContextAspectj.xml
package com.qian.springaopaspectj;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;/** * 将 代理类中 都要做得检查操作(横切性关注点模块化) * @author Administrator * */@Aspect //对横切性关注点的模块化;public class CheckInfoAspect { //定义advice应用到那些连接点上,也就是advice在应用程序上自行的点或者时机 //poincuName()就是给这个poincut起个名; @Pointcut("execution(* add*(..)) || execution(* find*(..))") private void poincutName(){} //advice也就是关注点的具体实现;before在连接点JointPoint的前面使用 @Before("poincutName()") public void checkInfo(){ System.out.println("Doing some checking things before method invocation"); }}
<?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:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> <!-- 告诉JVM 我们用了aspectj的 annotation --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> <bean id="realSubject" class="com.qian.realsubject.RealSubject"/> <bean id="checkInfoAspect" class="com.qian.springaopanno.CheckInfoAspect"/></beans>
5 Spring实现AOP的方式之aop-config
目标类:com.qian.realsubject.RealSubject
Advice类:com.qian.springaopxml.CheckInfoAspectXml
xml文件: applicationContextConfig.xml
package com.qian.springaopxml;/** * 模拟将遍布在系统流程中的检查信息(关注点)模块化成一个Aspect * @author Administrator * */public class CheckInfoAspectXml { public void checkInfo(){ System.out.println("Doing some checking things before method invocation"); }}
<?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:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> <bean id="realSubjectCGLIB" class="com.qian.realsubject.RealSubjectCGLIB"/> <bean id="checkInfoAspectXml" class="com.qian.springaopxml.CheckInfoAspectXml"/> <aop:config> <aop:aspect id="checkInfoAspectXml" ref="checkInfoAspectXml"> <aop:pointcut expression="execution(* com.qian.realsubject.RealSubjectCGLIB.add*(..))||execution(* find*(..))" id="pointcut"/> <aop:before method="checkInfo" pointcut-ref="pointcut"/> </aop:aspect> </aop:config></beans>
6 插曲,当目标类没有继承接口时,我们用CGLIB,并配置aop-config
类:com.qian.realsubject.RealSubjectCGLIB
Advice类:com.qian.springaopxml.CheckInfoAspectXml
xml文件: applicationContextConfigCGLIB.xml
package com.qian.realsubject;/** * 没有实现任何接口,我们用CGLIB来动态代理它 * @author Administrator * */public class RealSubjectCGLIB { public void addSub(String name, String password) { System.out.println("RealSubject.addSub() "+ name+" "+ password); } public String findSub(String id) { System.out.println("RealSubject.findSub() "+ id); return "realSubject.findSub()"; }}
<?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:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> <bean id="realSubjectCGLIB" class="com.qian.realsubject.RealSubjectCGLIB"/> <bean id="checkInfoAspectXml" class="com.qian.springaopxml.CheckInfoAspectXml"/> <aop:config> <aop:aspect id="checkInfoAspectXml" ref="checkInfoAspectXml"> <aop:pointcut expression="execution(* com.qian.realsubject.RealSubjectCGLIB.add*(..))||execution(* find*(..))" id="pointcut"/> <aop:before method="checkInfo" pointcut-ref="pointcut"/> </aop:aspect> </aop:config></beans>
7 Spring实现AOP的方式之POJO
目标类 : com.qian.realsubject.RealSubjectBean
Advice类: com.qian.springaopproxy.RealSubjectBeanHelper –实现了接口 AfterReturningAdvice, MethodBeforeAdvice
xml文件:applicationContextProxy.xml
package com.qian.realsubject;/** * 为了说明 CGLIB 和spring 可以在 JDK动态代理和CGLIB切换 * 定义了一个没有实现任何借口的普通类; * @author Administrator * */public class RealSubjectBean { private String subName; private String password; public String getSubName() { return subName; } public void setSubName(String subName) { this.subName = subName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public void addSubBean() { System.out.println("RealSubjectBean.addSubBean() "+ subName+" "+ password); } public String findSubBean(String subName) { System.out.println("RealSubjectBean.findSubBean() "+ subName); return "realSubjectBean.findSubBean()"; }}
package com.qian.springaopproxy;import java.lang.reflect.Method;import org.springframework.aop.AfterReturningAdvice;import org.springframework.aop.MethodBeforeAdvice;/** * 使用spring 典型的动态代理来处理 * @author Administrator * */public class RealSubjectHelper implements AfterReturningAdvice, MethodBeforeAdvice { public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable { System.out.println(" RealSubjectHelper BeforMehtod: checking information"); } public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable { System.out.println(" RealSubjectHelper AfterMehtod: checking information"); }}
<?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:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> <!-- (1) 注册Bean RealSubjectBean 和实现了 MethodBeforeAdvice AfterReturningAdvice接口的 RealSubjectHelper--> <bean id="realSubjectBean" class="com.qian.realsubject.RealSubjectBean"> <property name="subName" value="zhangsan"/> <property name="password" value="zhangsan123"/> </bean> <bean id="realSubjectHelper" class="com.qian.springaopproxy.RealSubjectHelper"/> <!-- (2) 使用正则表达式来表示切点Pointcut 使用类 JdkRegexpMethodPointcut--> <bean id="pointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut"> <property name="pattern" value=".*find.*"/> </bean> <!-- (3) 将横切点的具体实现 Advice 和 切点 Pointcut 联合起来 使用类 DefaultPointcutAdvisor--> <!-- <bean id="pointcutAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"> <property name="pointcut" ref="pointcut"/> <property name="advice" ref="realSubjectHelper"/> </bean> --> <bean id="pointcutAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"> <constructor-arg name="pointcut" ref="pointcut"/> <constructor-arg name="advice" ref="realSubjectHelper"/> </bean> <!-- (4) 生成目标对象RealSubjectBean的代理对象 使用类 ProxyFactoryBean --> <bean id="realSubjectBeanProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <!-- 目标对象 target --> <property name="target" ref="realSubjectBean"/> <!-- 拦截方法 --> <property name="interceptorNames"> <list> <value>pointcutAdvisor</value> </list> </property> </bean></beans>
对 7中的xml进行简化
xml文件: applicationContextProxyV2.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:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> <!-- (1) 注册Bean RealSubjectBean 和实现了 MethodBeforeAdvice AfterReturningAdvice接口的 RealSubjectHelper--> <bean id="realSubjectBean" class="com.qian.realsubject.RealSubjectBean"> <property name="subName" value="zhangsan"/> <property name="password" value="zhangsan123"/> </bean> <bean id="realSubjectHelper" class="com.qian.springaopproxy.RealSubjectHelper"/> <!-- (2) 使用正则表达式来表示切点Pointcut 和 横切点的具体实现Advice自动联合 使用类 RegexpMethodPointcutAdvisor--> <bean id="pointcutAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="pattern" value=".*find.*"/> <property name="advice" ref="realSubjectHelper"/> </bean> <!-- (3) 生成目标对象RealSubjectBean的代理对象 使用类自动代理生成器 DefaultAdvisorAutoProxyCreator--> <bean id="realSubjectBeanProxy" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/></beans>
8 最主要的Client类
package com.qian.client;import com.qian.realsubject.RealSubject;import com.qian.realsubject.RealSubjectBean;import com.qian.realsubject.RealSubjectCGLIB;import com.qian.staticproxy.SubjectStaticProxy;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.qian.danamicproxy.SubjectDanamicProxy;import com.qian.subject.Subject;/** * Client主测试类 * @author Administrator * */public class Client { //最通俗易懂的办法 但是耦合度太高了 public static void subjectImpl(){ Subject subject = new RealSubject(); subject.addSub("qian", "520"); subject.findSub("511"); } // 静态代理 public static void staticProxy(){ Subject subject = new SubjectStaticProxy(new RealSubject()); subject.addSub("name", "password"); subject.findSub("123"); } // 动态代理 public static void dynamicProxy(){ Object proxy = new SubjectDanamicProxy().getSubjectProxy(new RealSubject()); Subject subject = (Subject)proxy; subject.addSub("zhangsan", "pass123"); subject.findSub("134"); } //使用 Aspectj.jar 和Aspectjweaver.jar 进行注释 推崇 public static void springaopAspectj(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContextAspectj.xml"); Subject subject = (Subject) context.getBean("realSubject"); subject.addSub("spring", "aop"); subject.findSub("1231"); } //使用spring的aop-config进行配置、推崇 public static void springaopConfig(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContextConfig.xml"); Subject subject = (Subject) context.getBean("realSubject"); subject.addSub("spring", "aop"); subject.findSub("1231"); } //对没有实现接口的类使用CGLIB 并使用spring的aop-config进行配置 public static void springaopConfigCGLIB(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContextAopConfigCGLIB.xml"); RealSubjectCGLIB subject = (RealSubjectCGLIB) context.getBean("realSubjectCGLIB"); subject.addSub("spring", "aop"); subject.findSub("1231"); } //spring AOP动态代理 public static void springaopProxy(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContextProxy.xml"); RealSubjectBean subjectBean = (RealSubjectBean) context.getBean("realSubjectBeanProxy"); subjectBean.addSubBean(); subjectBean.findSubBean("springaop4"); } //spirng AOP自动进行匹配的动态代理 public static void springaopProxyV2(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContextProxyV2.xml"); RealSubjectBean subjectBean = (RealSubjectBean) context.getBean("realSubjectBean"); subjectBean.addSubBean(); subjectBean.findSubBean("springaop4"); } public static void main(String[] args) { //subjectImpl(); //staticProxy(); //dynamicProxy(); //springaopConfig(); //springaopConfigCGLIB(); //springaopProxy(); //springaopProxyV2(); }}
结果都是预期的结果这里就不显示了。
本project使用的是Maven建的、所以pom.xml如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>springaop</groupId> <artifactId>SpringAop</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.3.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>4.3.0.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.5</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.5</version> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.2.0</version> </dependency> </dependencies></project>
如果有想找完整版的src文件的朋友,可以留邮箱、
Thank you for your consideration. Thanks everyone. And I am grateful to those who give any comments or suggestions in the futrue.
- Spring AOP:静态代理、动态代理和几种常见的aop配置
- spring AOP 静态代理和动态代理
- 动态代理和静态代理以及spring的aop
- 动态代理和静态代理以及spring的aop
- Spring AOP 静态代理与动态代理
- spring aop proxy 静态代理和动态代理
- Spring -AOP -java静态代理和动态代理实例
- Spring AOP配置 动态代理
- Spring AOP和动态代理
- spring aop和动态代理
- Spring AOP 代理实现的两种方式: JDK动态代理 和 Cglib框架动态代理
- spring(AOP)静态代理、JDK动态代理、cglib实现代理
- 动态代理AOP的配置
- Spring AOP实践(一)动态代理和静态代理,为什么使用AOP
- 基于Spring AOP的JDK动态代理和CGLIB代理
- Spring Aop 动态代理
- Spring AOP动态代理
- Spring AOP 动态代理
- 用ORACLE的PROFILE限制ORACLE用户word版
- Unity3D基础笔迹
- 数据库索引设计与优化pdf
- 数据库原理与实务pdf
- 数据库系统工程师考试试题分类精解pdf
- Spring AOP:静态代理、动态代理和几种常见的aop配置
- 游戏人工智能编程案例精粹pdf
- 淘宝MySQL十大经典案例pdf
- Android O 趟过的那些坑
- 游戏设计的236个技巧pdf
- Visual FoxPro权威指南pdf
- 如何实现鼠标悬浮时半透明的按钮背景变得更浅或更深啊
- Oracle.DBA手记·4:数据安全警示录pdf
- SQLite权威指南(第二版)pdf