Spring中AOP的模拟实现
什么是AOP?
面向切面编程(AOP)完善spring的依赖注入(DI),面向切面编程在spring中主要表现为两个方面
1.面向切面编程提供声明式事务管理
2.spring支持用户自定义的切面
面向切面编程(aop)是对面向对象编程(oop)的补充,
面向对象编程将程序分解成各个层次的对象,面向切面编程将程序运行过程分解成各个切面。
AOP从程序运行角度考虑程序的结构,提取业务处理过程的切面,oop是静态的抽象,aop是动态的抽象,
是对应用执行过程中的步骤进行抽象,,从而获得步骤之间的逻辑划分。
aop框架具有的两个特征:
1.各个步骤之间的良好隔离性
2.源代码无关性
前提:要实现AOP的模拟就要知道动态代理,Spring中使用了两种动态代理方式,一种是基于JDK的动态代理,一种是基于CGlib的动态代理。为什么会有两种,那是因为JDK的动态代理只能是
针对接口。
先看下面的代码dao层
Java代码
package com.lbx.dao;
import com.lbx.model.User;
public interface UserDAO {
public void save(User user);
//public void delete();
}
dao实现层
Java代码
package com.lbx.dao.impl;
import com.lbx.dao.UserDAO;
import com.lbx.model.User;
public class UserDAOImpl implements UserDAO {
@Override
public void save(User user) {
System.out.println("a user saved!!!");
}
/*public void delete(){
System.out.println("UserDAOImpl.delete()");
}
*/
}
现在我们要在User的save之前和之后做一些处理(拦截器),我们先看一种最简单的方法(在类中加代码)
Java代码
package com.lbx.dao.impl;
import com.lbx.dao.UserDAO;
import com.lbx.model.User;
public class UserDAOImpl1 implements UserDAO {
@Override
public void save(User user) {
System.out.println("method start....");
System.out.println("a user saved!!!");
System.out.println("method stoped...");
}
}
显然,这是可以的,但是这样明显就不好,第一代码没可重用性,第二这是在知道源码的情况下,现实中我们有很多情况都不知道源码,在这种情况下,明显这方式就不行了。下面就是第二
种解决方案:
Java代码
package com.lbx.dao.impl;
import com.lbx.model.User;
public class UserDAOImpl2 extends UserDAOImpl{
public void save(User user) {
System.out.println("method start....");
super.save(user);
System.out.println("method stoped.....");
}
}
先让一个类实现了那个接口,然后要用的类继承那个实现类,这样也可以达到目的(其实这就是一种“组合模式”),这种方式在一定的程度上是利用的资源,代码的重用性。但是还是不好
,当我们要做很多的处理的时候,这样我们就要组合和多的类,明显就不好。下面是第三种:使用动态代理。 先看处理方法(拦截器)
Java代码
package com.lbx.interceptor;
public class UserInterceptor {
//第一个拦截方法
public void method1(){
System.out.println("UserInterceptor.method1()");
}
//第二个拦截方法
public void method2(){
System.out.println("UserInterceptor.method2()");
}
}
产生代理的类,实现InvocationHandler接口
Java代码
package com.lbx.interceptor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ProxyHandler implements InvocationHandler {
//创建需要代理的目标对象
private Object targer;
//创建拦截器的实例
UserInterceptor u = new UserInterceptor();
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
//if(method.getName().equals("save")){
u.method1();
result = method.invoke(targer, args);
u.method2();
//}else{
//result = method.invoke(targer, args);
//}
return result;
}
//用于设置传人目标对象的方法
public void setTarger(Object o){
this.targer = o;
}
}
获得代理的实例类
Java代码
package com.lbx.interceptor;
import java.lang.reflect.Proxy;
import com.lbx.dao.impl.UserDAOImpl;
public class UserProxyFactory {
public static Object getProxy(Object object){
ProxyHandler p = new ProxyHandler();
p.setTarger(object);
return Proxy.newProxyInstance(UserDAOImpl.class.getClassLoader(), object.getClass().getInterfaces(), p);
}
}
服务层使用动态代理
Java代码
package com.lbx.service;
import com.lbx.dao.UserDAO;
import com.lbx.dao.impl.UserDAOImpl;
import com.lbx.interceptor.UserProxyFactory;
import com.lbx.model.User;
public class UserService {
//private UserDAO userDAO = new UserDAOImpl1(); //第一种就是写死,直接在方法里写
//private UserDAO userDAO = new UserDAOImpl2(); //第二种就是通过继承来实现(方法执行前后加一些业务逻辑)
//private UserDAO userDAO = new UserDAOImpl3(); //第三种是通过组合来完成的
UserDAO userDAO = new UserDAOImpl();
UserDAO u = null;
Object object = UserProxyFactory.getProxy(userDAO);
/*public UserDAO getUserDAO() {
return userDAO;
}
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}*/
/*public void add(User user){
this.userDAO.save(user);
}*/
public void add(User user){
if(object instanceof UserDAO){
u = (UserDAO)object;
}
u.save(user);
//u.delete();
}
}
Spring中AOP的模拟实现的更多相关文章
- Spring中AOP相关的API及源码解析
Spring中AOP相关的API及源码解析 本系列文章: 读源码,我们可以从第一行读起 你知道Spring是怎么解析配置类的吗? 配置类为什么要添加@Configuration注解? 谈谈Spring ...
- Spring中AOP原理,源码学习笔记
一.AOP(面向切面编程):通过预编译和运行期动态代理的方式在不改变代码的情况下给程序动态的添加一些功能.利用AOP可以对应用程序的各个部分进行隔离,在Spring中AOP主要用来分离业务逻辑和系统级 ...
- Spring中AOP简介与切面编程的使用
Spring中AOP简介与使用 什么是AOP? Aspect Oriented Programming(AOP),多译作 "面向切面编程",也就是说,对一段程序,从侧面插入,进行操 ...
- 框架源码系列十:Spring AOP(AOP的核心概念回顾、Spring中AOP的用法、Spring AOP 源码学习)
一.AOP的核心概念回顾 https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/core.html#a ...
- Spring 中aop切面注解实现
spring中aop的注解实现方式简单实例 上篇中我们讲到spring的xml实现,这里我们讲讲使用注解如何实现aop呢.前面已经讲过aop的简单理解了,这里就不在赘述了. 注解方式实现aop我们 ...
- Spring中AOP相关源码解析
前言 在Spring中AOP是我们使用的非常频繁的一个特性.通过AOP我们可以补足一些面向对象编程中不足或难以实现的部分. AOP 前置理论 首先在学习源码之前我们需要了解关于AOP的相关概念如切点切 ...
- AOP 与 Spring中AOP使用(上)
AOP简介 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程, 通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. AOP是OOP的延续 ...
- JAVA高级架构师基础功:Spring中AOP的两种代理方式:动态代理和CGLIB详解
在spring框架中使用了两种代理方式: 1.JDK自带的动态代理. 2.Spring框架自己提供的CGLIB的方式. 这两种也是Spring框架核心AOP的基础. 在详细讲解上述提到的动态代理和CG ...
- 浅析Spring中AOP的实现原理——动态代理
一.前言 最近在复习Spring的相关内容,刚刚大致研究了一下Spring中,AOP的实现原理.这篇博客就来简单地聊一聊Spring的AOP是如何实现的,并通过一个简单的测试用例来验证一下.废话不 ...
随机推荐
- CSS代码实现图片防盗链
CSS代码实现图片防盗链的方法其实很简单.在CSS文件中添加以下代码: img { filter:exPRession( this.不能去掉 ? "" : ( (!this.com ...
- JVM监控概述(图文)
JVM内存分配概述 Jvm 内存分为:堆.非堆及直接内存三大块. 堆区分为年轻代和老年代,永生代属于非堆内存. 对象优先在Eden区分配 大对象直接进入老年代 长期存活的对象将进入老年代 class. ...
- 思维方式--SMART原则
假设你的项目管理.系统架构的兴趣,请加微信订阅号"softjg",收藏此PM.建筑师的家 万事开头于你目标的设定,假设開始走错了,那么后面的路将会更加的错误.甚至于更加的努力犯错就 ...
- Windows 7的 磁盘管理中,某个磁盘或分区,突然变成只读。
1.今天突然发现E盘无法创建文件夹.文件,也不可以改,感觉像是变成只读 . 2.我的电脑 -> 计算机管理 -> 存储 -> 磁盘管理,发现E盘下面标记着只读两个字. 3.由于我的E ...
- python向mysql中存储JSON及Nodejs取出
虽然把JSON数据存入mysql也是比较蛋疼,但是相比使用Nodejs嵌套处理多个mysql查询并拼接返回数据也算是没mongo时的一个折中方案了. 我使用python拼接了一个json格式的字符串, ...
- mvc拦截器
在ASP.NET MVC中,有三种拦截器:Action拦截器.Result拦截器和Exception拦截器.这里说的是第一种和第三种.其实所谓的ASP.NET MVC拦截器,也没什么神秘的,就是一个普 ...
- printf详解
用了这么多年c了,今天想编个小程序练练手,忽然发现对于printf这个函数并不甚了解.上网查了查,下面是对printf()的详解: 函数原型: #include <stdio.h> int ...
- sql内置函数pivot强大的行转列功能
原文:sql内置函数pivot强大的行转列功能 语法: PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT的一般语法是:PIVO ...
- hadoop大数据处理之表与表的连接
hadoop大数据处理之表与表的连接 前言: hadoop中表连接其实类似于我们用sqlserver对数据进行跨表查询时运用的inner join一样,两个连接的数据要有关系连接起来,中间必须有一个 ...
- 关于lower_bound的使用
突然发现lower_bound是一个挺好用的东西, 在学习最长不下降子序列的nlogn的算法的时候看到的,C++党写起二分来一行- -P党一排233 感觉如果到时候需要用上二分的话,能用lower_b ...