Spring_代理
1.代理模式。
2.静态代理原理及实践。
3.动态代理原理及实践。
4.Spring AOP原理及实战。
静态代理原理及实践
package test.staticProxy;
// 接口
public interface IUserDao {
void save();
void find();
}
//目标对象
class UserDao implements IUserDao{
@Override
public void save() {
System.out.println("模拟:保存用户!");
}
@Override
public void find() {
System.out.println("模拟:查询用户");
}
}
/**
静态代理
特点:
1. 目标对象必须要实现接口
2. 代理对象,要实现与目标对象一样的接口
*/
class UserDaoProxy implements IUserDao{
// 代理对象,需要维护一个目标对象
private IUserDao target = new UserDao();
@Override
public void save() {
System.out.println("代理操作: 开启事务...");
target.save(); // 执行目标对象的方法
System.out.println("代理操作:提交事务...");
}
@Override
public void find() {
target.find();
}
}
静态代理的缺点:
代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理
如果增加一个方法,除了实现类需要实现这个方法外,所有的代理类也要实现此方法,增加了代码的 维护成本,使用动态代理可以解决
动态代理原理及实践
package com.tanlei.test; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; /**
* @author <a href="mailto:lei.tan@vtradex.net">谭磊</a>
* @since 2019-01-02 17:16
*/ //动态代理: 代理工厂,给多个目标对象生成代理对象
public class ProxyFactory {
//接收一个目标对象
private Object target;
public ProxyFactory(Object target){
this.target=target;
} //返回目标对象(target)代理后的对象(Proxy)
public Object getProxyInstance(){
Object proxy= Proxy.newProxyInstance(
target.getClass().getClassLoader(),//目标对象使用的 类加载器
target.getClass().getInterfaces(), //目标对象实现的 所有接口
new InvocationHandler() { //执行代理对象方法时触发
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//获取当前执行的方法的方法名
String methodName=method.getName();
//方法返回值
Object result=null;
if("find".equals(methodName)){
//直接调用目标对象方法
result=method.invoke(target, args);
}else{
System.out.println("开启事务...");
//执行目标对象方法
result=method.invoke(target, args);
System.out.println("提交事务...");
}
return result;
}
}
);
return proxy;
} }
package com.tanlei.test; /**
* @author <a href="mailto:lei.tan@vtradex.net">谭磊</a>
* @since 2019-01-02 17:04
*/
public class Main {
public static void main(String[] args) {
//创建目标对象
IUserDao target=new UserDao();
System.out.println("目标对象: "+target.getClass()); //代理对象
IUserDao proxy= (IUserDao) new ProxyFactory(target).getProxyInstance();
System.out.println("代理对象: "+proxy.getClass()); //执行代理对象的方法
proxy.save(); }
}
缺点:
使用jdk生成的动态代理的前提是目标类必须有实现的接口。但这里又引入一个问题,如果某个类没有实现接口,就不能使用JDK动态代理,所以Cglib代理就是解决这个问题的。
spring AOP原理及实战
AOP的定义:面向切面编程,核心原理是使用动态代理模式在方法执行前后或出现异常时加入相关逻辑。
通过定义和前面代码我们可以发现3点:
1.AOP是基于动态代理模式。
2.AOP是方法级别的(要测试的方法不能为static修饰,因为接口中不能存在静态方法,编译就会报错)。
3.AOP可以分离业务代码和关注点代码(重复代码),在执行业务代码时,动态的注入关注点代码。切面就是关注点代码形成的类。
Spring是如何生成代理对象的?:
1.创建容器对象的时候,根据切入点表达式拦截的类,生成代理对象。
2.如果目标对象有实现接口,使用jdk代理。如果目标对象没有实现接口,则使用Cglib代理。然后从容器获取代理后的对象,在运行期植入"切面"类的方法。通过查看Spring源码,我们在DefaultAopProxyFactory类中,找到这样一段话。
知道了原理,现在我们将自己手动实现Spring的AOP:
package test.spring_aop_anno;
import org.aspectj.lang.ProceedingJoinPoint;
public interface IUserDao {
void save();
}
//用于测试Cglib动态代理
class OrderDao {
public void save() {
//int i =1/0;用于测试异常通知
System.out.println("保存订单...");
}
}
//用于测试jdk动态代理
class UserDao implements IUserDao {
public void save() {
//int i =1/0;用于测试异常通知
System.out.println("保存用户...");
}
}
//切面类
class TransactionAop {
public void beginTransaction() {
System.out.println("[前置通知] 开启事务..");
}
public void commit() {
System.out.println("[后置通知] 提交事务..");
}
public void afterReturing(){
System.out.println("[返回后通知]");
}
public void afterThrowing(){
System.out.println("[异常通知]");
}
public void arroud(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("[环绕前:]");
pjp.proceed(); // 执行目标方法
System.out.println("[环绕后:]");
}
}
Spring的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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="userDao" class="test.spring_aop_anno.UserDao">bean> <bean id="orderDao" class="test.spring_aop_anno.OrderDao">bean> <bean id="transactionAop" class="test.spring_aop_anno.TransactionAop">bean> <aop:config> <aop:pointcut expression="execution(* test.spring_aop_anno.*Dao.*(..))" id="transactionPointcut"/> <aop:aspect ref="transactionAop"> <aop:around method="arroud" pointcut-ref="transactionPointcut"/> <aop:before method="beginTransaction" pointcut-ref="transactionPointcut" /> <aop:after method="commit" pointcut-ref="transactionPointcut"/> <aop:after-returning method="afterReturing" pointcut-ref="transactionPointcut"/> <aop:after-throwing method="afterThrowing" pointcut-ref="transactionPointcut"/>
aop:aspect>
aop:config>
beans>
package com.tanlei.Aop; import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; /**
* @author <a href="mailto:lei.tan@vtradex.net">谭磊</a>
* @since 2019-01-03 16:32
*/
public class Main {
private ApplicationContext context=new ClassPathXmlApplicationContext("applicationcontext_xml.xml"); @Test
public void testProxy(){
//SpringIOC容器中获取对象,测试spring中jdk动态代理方式
IUserDao userDao= (IUserDao) context.getBean("userDao");
System.out.println(userDao.getClass());
userDao.save();
} @Test
public void testCglib(){
// SpringIOC容器中获取对象,测试spring中Cglib动态代理方式
OrderDao orderDao= (OrderDao) context.getBean("orderDao");
System.out.println(orderDao.getClass());
orderDao.save();
} }
到这里,我们已经全部介绍完Spring AOP,回到开篇的问题,我们拿它做什么?
1.Spring声明式事务管理配置。
2.Controller层的参数校验。
3.使用Spring AOP实现MySQL数据库读写分离案例分析
4.在执行方法前,判断是否具有权限。
5.对部分函数的调用进行日志记录。监控部分重要函数,若抛出指定的异常,可以以短信或邮件方式通知相关人员。
6.信息过滤,页面转发等等功能,
Spring_代理的更多相关文章
- Spring_总结_04_高级配置(四)_bean的作用域
一.前言 本文承接上一节:Spring_总结_04_高级配置(三)之处理歧义 1.单例bean Spring应用上下文中所有的bean默认都是单例的.也就是说,不管一个bean被注入到其他bean多少 ...
- 【原】谈谈对Objective-C中代理模式的误解
[原]谈谈对Objective-C中代理模式的误解 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这篇文章主要是对代理模式和委托模式进行了对比,个人认为Objective ...
- nginx配置反向代理或跳转出现400问题处理记录
午休完上班后,同事说测试站点访问接口出现400 Bad Request Request Header Or Cookie Too Large提示,心想还好是测试服务器出现问题,影响不大,不过也赶紧上 ...
- Visual Studio Code 代理设置
Visual Studio Code (简称 VS Code)是由微软研发的一款免费.开源的跨平台文本(代码)编辑器,在十多年的编程经历中,我使用过非常多的的代码编辑器(包括 IDE),例如 Fron ...
- DynamicObject - 代理对象的种类
开箱即用,DynamicProxy提供了多种代理对象,主要分成两个大类: 基于继承(Inheritance-based) 基于继承的代理是通过继承一个代理类来实现,代理拦截对类的虚(virtual)成 ...
- SignalR代理对象异常:Uncaught TypeError: Cannot read property 'client' of undefined 推出的结论
异常汇总:http://www.cnblogs.com/dunitian/p/4523006.html#signalR 后台创建了一个DntHub的集线器 前台在调用的时候出现了问题(经检查是代理对象 ...
- 实现代理设置proxy
用户在哪些情况下是需要设置网络代理呢? 1. 内网上不了外网,需要连接能上外网的内网电脑做代理,就能上外网:多个电脑共享上外网,就要用代理: 2.有些网页被封,通过国外的代理就能看到这被封的网站:3. ...
- 23种设计模式--代理模式-Proxy
一.代理模式的介绍 代理模式我们脑袋里出现第一个词语就是代购,其实就是这样通过一个中间层这个中间成是属于什么都干什么都买得,俗称"百晓生",在平时得开发中我们经常会听到 ...
- 使用Java原生代理实现AOP
### 本文由博主柒.原创,转载请注明出处 ### 完整源码下载地址 [https://github.com/MatrixSeven/JavaAOP](https://github.com/Matri ...
随机推荐
- 群晖引导是uefi还是传统模式的识别
看左下角光标闪不闪,不闪的是uefi,在闪的就是传统
- AOP的几种实现方法
C# 实现AOP 的几种常见方式 原文出处:http://www.cnblogs.com/zuowj/p/7501896.html AOP为Aspect Oriented Programming的缩写 ...
- Struts2接受请求参数三种常用方法
一 接受请求参数主要有三种:属性驱动 对象驱动 模型驱动<model Driven> 方式1:在Action中接收请求参数不需要使用request对象,在Action中定义与请求参数相同名 ...
- java基础之BigDecimal类
由于在运算的时候,float类型和double很容易丢失精度,演示案例.所以,为了能精确的表示.计算浮点数,Java提供了BigDecimal BigDecimal类概述 不可变的.任意精度的有符号十 ...
- Django项目: 3.用户注册功能
本章内容的补充知识点 导入库的良好顺序: 1.系统库 2.django库 3.自己定义的库(第三方库) redis缓存数据库的数据调用速度快,但是不利于长时间保存. mysql用于长时间存储,但是调用 ...
- java笔试之取近似值
写出一个程序,接受一个正浮点数值,输出该数值的近似整数值.如果小数点后数值大于等于5,向上取整:小于5,则向下取整. package test; import java.util.*; import ...
- PIL的ImageDraw的颜色问题
因为我的图片的单通道的,所以用 draw = ImageDraw.Draw(image) im_width, im_height =], info[], info[], info[]) color=d ...
- HBase 数据坐标
- 如何解决mysql服务器load高
.登录主机 # ssh hostname .确定是否是mysql导致 # top .查看是哪些sql正在慢查询 # mysql -h hostname -P port -u username # sh ...
- js的简单介绍和相关的必备常识
一.概念 1.js是JavaScript的缩写,是运行在浏览器端或服务端的依附于页面的脚本语言. 2.js的学习分为:ECMA语法.Dom网页对象模型.Bom浏览器的对象模型 3.ECMA是浏览器厂商 ...