Spring AOP中的动态代理机制
来源:互联网 发布:大英雄郑成功 知乎 编辑:程序博客网 时间:2024/05/15 07:05
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);}
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;}}
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("执行完毕");}}
ActionTest测试类代码
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);}@Overridepublic 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) {//创建代理对象iuserServLogHandler 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"/>
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("开始执行");}}
(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("执行完毕");}}
(c)在spring容器中,让容器管理通知(applicationContext.xml)
<!-- 定义通知 --><!-- 前置通知 --><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>
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();}}
运行结果:
开始执行
******执行删除方法******
执行完毕
开始执行
*******执行查询方法*******
执行完毕
四.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("执行完毕");}}
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>
测试类:
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.*.*(..))"/>
运行结果:
开始执行
******执行删除方法******
执行完毕
开始执行
*******执行查询方法*******
执行完毕
开始执行
*******执行添加方法********
执行完毕
文章转自:Spring AOP动态代理原理与实现方式
- Spring AOP中的动态代理实现机制
- Spring AOP中的动态代理机制
- Spring AOP 动态代理机制
- Spring AOP 动态代理机制
- Spring AOP原理——Java中的动态代理机制
- Spring AOP中的动态代理
- Spring AOP中的动态代理
- java中的动态代理机制实现AOP
- spring中的ioc,aop。动态代理
- 动态代理在Spring AOP中的应用
- Spring中的AOP操作(动态代理)
- Spring AOP 代理机制
- Spring AOP代理机制
- Spring AOP 代理机制
- Spring AOP 代理机制
- Spring Aop 动态代理
- Spring AOP动态代理
- Spring AOP 动态代理
- 嵌入式从业者应注意的问题
- CNN简介
- node.js 安装手册
- Linux防火墙iptables的策略
- Charles限流
- Spring AOP中的动态代理机制
- 同步监视器之同步代码块、同步方法
- 使用eclipse创建一个maven+springMVC工程
- PHP函数可变函数列表
- 一步一步解决一个机器学习问题
- hdu3790-最短路径最小值
- C语言指针传递和内存分配
- 【二叉树经典问题】100. Same Tree
- web服务器与ftp服务器的区别