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_代理的更多相关文章

  1. Spring_总结_04_高级配置(四)_bean的作用域

    一.前言 本文承接上一节:Spring_总结_04_高级配置(三)之处理歧义 1.单例bean Spring应用上下文中所有的bean默认都是单例的.也就是说,不管一个bean被注入到其他bean多少 ...

  2. 【原】谈谈对Objective-C中代理模式的误解

    [原]谈谈对Objective-C中代理模式的误解 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这篇文章主要是对代理模式和委托模式进行了对比,个人认为Objective ...

  3. nginx配置反向代理或跳转出现400问题处理记录

    午休完上班后,同事说测试站点访问接口出现400 Bad Request  Request Header Or Cookie Too Large提示,心想还好是测试服务器出现问题,影响不大,不过也赶紧上 ...

  4. Visual Studio Code 代理设置

    Visual Studio Code (简称 VS Code)是由微软研发的一款免费.开源的跨平台文本(代码)编辑器,在十多年的编程经历中,我使用过非常多的的代码编辑器(包括 IDE),例如 Fron ...

  5. DynamicObject - 代理对象的种类

    开箱即用,DynamicProxy提供了多种代理对象,主要分成两个大类: 基于继承(Inheritance-based) 基于继承的代理是通过继承一个代理类来实现,代理拦截对类的虚(virtual)成 ...

  6. SignalR代理对象异常:Uncaught TypeError: Cannot read property 'client' of undefined 推出的结论

    异常汇总:http://www.cnblogs.com/dunitian/p/4523006.html#signalR 后台创建了一个DntHub的集线器 前台在调用的时候出现了问题(经检查是代理对象 ...

  7. 实现代理设置proxy

    用户在哪些情况下是需要设置网络代理呢? 1. 内网上不了外网,需要连接能上外网的内网电脑做代理,就能上外网:多个电脑共享上外网,就要用代理: 2.有些网页被封,通过国外的代理就能看到这被封的网站:3. ...

  8. 23种设计模式--代理模式-Proxy

    一.代理模式的介绍       代理模式我们脑袋里出现第一个词语就是代购,其实就是这样通过一个中间层这个中间成是属于什么都干什么都买得,俗称"百晓生",在平时得开发中我们经常会听到 ...

  9. 使用Java原生代理实现AOP

    ### 本文由博主柒.原创,转载请注明出处 ### 完整源码下载地址 [https://github.com/MatrixSeven/JavaAOP](https://github.com/Matri ...

随机推荐

  1. <scrapy爬虫>爬取校花信息及图片

    1.创建scrapy项目 dos窗口输入: scrapy startproject xiaohuar cd xiaohuar 2.编写item.py文件(相当于编写模板,需要爬取的数据在这里定义) # ...

  2. HtmlHelper2

    一.隐式从ViewBag取数据 1.action中的代码: ViewBag.UserName = "admin"; cshtml中的代码: @Html.TextBox(" ...

  3. css 实现头像周围光圈动态效果

    效果: html文件: <img class="userHead" src="xx/user.jpg"> css文件: .userHead{ wid ...

  4. PLSQL远程访问Oracle数据库配置

    PLSQL远程访问Oracle数据库的配置 监听器(LISTENER) :监听器是Oracle基于服务器端的一种网络服务,主要用于监听客户端向数据库服务器端提出的连接请求.既然是基于服务器端的服务,那 ...

  5. ERP或PLM系统-物料编码管理的技术实现

    1 企业现状 企业日常经营过程中会产生大量的文档,如设计图纸.变更单.计算书.设计方案等,如果是制造企业还会产生大量的产品.组成产品的零部件等物料,这些数据在进入信息系统前都需要有一个唯一的标识,也就 ...

  6. 获取地址栏URL中参数, getQuerySting()方法

    今天同事用的以前的获取url地址参数获取不到.以前的方法失效了.后面发现是正则表达式bug: 第一种获取方法(针对普通情况的一般够用): function getQueryString(name) { ...

  7. C++中int型与char型相互转换的问题

    参考:https://www.cnblogs.com/dj-917366761-bg/p/7078078.html 主要针对0~9这几个数字. 可以借助 ‘0’. char 转 int —— int ...

  8. centos7 盘符变动 绑定槽位

    服务器下的硬盘主有机械硬盘.固态硬盘以及raid阵列,通常内核分配盘符的顺序是/dev/sda./dev/sdb… ….在系统启动过程中,内核会按照扫描到硬盘的顺序分配盘符(先分配直通的,再分配阵列) ...

  9. vue项目 环境搭建

    1.前端安装 安装项目:vue init webpack docvote 进入docvote里:cd docvote 安装脚手架:cnpm i 运行:npm run dev 2.异步加载 const ...

  10. python实现简单的百度翻译

    这段时间,一直在学python,想找点东西实现一下,练手,所以我想通过python代码来实现翻译,话不多说,看吧! 以chrome为例 1  打开百度翻译 https://fanyi.baidu.co ...