1. 分析程序中存在的问题(高内聚,低耦合)
        通过springIOC DI) 以及注解的使用,成功解决了在程序中层与层之间出现的耦合的问题,但是在很多地方仍然存在非该层应该实现的功能,造成了 无法“高内聚”的现象,同时存在大量存在重复代码,开发效率低下。

   @Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao; @Override
public void registUser(User user) {
try {
System.out.println("校验权限。。。");
System.out.println("开启事务。。。");
System.out.println("记录日志。。。");
userDao.addUser(user);
System.out.println("提交事务。。。");
} catch (Exception e) {
System.out.println("回滚事务");
e.printStackTrace();
}
} @Override
public void upToVIP(User user) {
try {
System.out.println("校验权限。。。");
System.out.println("开启事务。。。");
System.out.println("记录日志。。。");
userDao.updateUser(user);
System.out.println("提交事务。。。");
} catch (Exception e) {
System.out.println("回滚事务");
e.printStackTrace();
} } @Override
public void removeUser(User user) {
try {
System.out.println("校验权限。。。");
System.out.println("开启事务。。。");
System.out.println("记录日志。。。");
userDao.deleteUser(user.getId());
System.out.println("提交事务。。。");
} catch (Exception e) {
System.out.println("回滚事务");
e.printStackTrace();
}
} }
此时可以通过代理设计模式,将这部分代码提取到代理者中,简化层中的代码。 2. 静态代理模式
package cn.tedu.staticproxy;
public interface SJSkill {
public void 吃();
public void 唱歌();
} package cn.tedu.staticproxy;
public class FBB implements SJSkill{
public void 吃(){
System.out.println("fbb吃饭。。。");
}
public void 唱歌(){
System.out.println("fbb唱歌。。。");
}
} package cn.tedu.staticproxy;
public class JJRStaticProxy implements SJSkill{ private FBB fbb = new FBB(); @Override
public void 吃() {
System.out.println("权限认证:你谁啊????");
fbb.吃();
System.out.println("记录日志:等我,我记一下来访记录");
} @Override
public void 唱歌() {
System.out.println("权限认证:你谁啊????");
fbb.唱歌();
System.out.println("记录日志:等我,我记一下来访记录");
} } package cn.tedu.staticproxy;
import org.junit.Test;
public class StaticProxyTest {
@Test
public void test01(){
JJRStaticProxy jjr = new JJRStaticProxy();
jjr.吃();
jjr.唱歌();
}
}       

静态代理设计模式特点:
            优点:
                结构清晰 易于理解
            缺点:
                如果被代理者有多个方法,则代理者也需要开发多个方法,其中往往存在大量重复代码,仍然存在代码重复。
        
        静态代理设计模式解决了软件分层过程中 额外的功能代码侵入模块的问题,将额外的功能代码提取到了代理者中进行,但是静态代理实现的代理者中存在大量重复的代码,并没有解决代码重复问题。所以在真正开发中--包括spring的底层,基本不会使用静态代理。
        
    3. 动态代理 - jdk内置的动态代理
        在jdk中提供了动态代理实现的工具类,直接使用该工具类就可以创建出代理者,并且可以通过内置的回调函数指定代理在工作时的执行逻辑,从而实现基于jdk原生api的动态代理机制。
            java.lang.reflect
            类 Proxy
            java.lang.Object
            static Object    newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
                          返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
        
        案例:

       package cn.tedu.javaproxy;

             import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; import org.junit.Test; public class JavaProxyTest {
@Test
public void test01(){ //被代理者
final FBB fbb = new FBB(); //java动态代理方式 生成fbb的代理者
/**
* classLoader:用来生成代理者类的类加载器,通常可以传入被代理者类的类加载器
* interfaces: 要求生成的代理者实现的接口们,通常就是实现和被代理者相同的接口,保证具有和被代理者相同的方法
* invocationHandler: 用来设定回调函数的回调接口,使用者需要写一个类实现此接口,从而实现其中的invoke方法,
* 在其中编写代码处理代理者调用方法时的回调过程,通常在这里调用真正对象身上的方法,并且在方法之前或之后做额外操作。
*/
SJSkill proxy = (SJSkill) Proxy.newProxyInstance(FBB.class.getClassLoader(),FBB.class.getInterfaces()
,new InvocationHandler() {
@Override
/**
* proxy: 代理者
* method:当前调用的方法对象 由被代理的方法调用
* args:挡墙调用的方法的参数数组 方法调用的参数
*/
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
if("拍电影".equals(method.getName())){
System.out.println("不好意思,给多少钱不拍了~~");
return null;
}else{
System.out.println("检验权限。。。。");
Object returnObj = method.invoke(fbb, args);
System.out.println("记录日志。。。。");
return returnObj;
}
}
});
//从此之后,不允许直接调用被代理者身上的方法,而是要通过代理者来调用
//fbb.吃();
//fbb.唱歌();
proxy.吃();
proxy.唱歌();
proxy.拍电影();
}
}

java动态代理的原理图:

java动态代理的特点:
            优点:
                不需要像静态代理一样被代理方法都要实现一遍,而只需要在回调函数中进行处理就可以了,重复代码只需编写一次。
            缺点:
                java的动态代理是通过代理者实现和被代理者相同的接口来保证两者具有相同的方法的,如果被代理者想要被代理的方法不属于任何接口,则生成的代理者自然无法具有这个方法,也就无法实现对该方法的代理。
                所以java的动态代理机制是基于接口进行的,受制于要代理的方法是否有接口的支持。
    
    4. 动态代理 - 第三方包cglib实现的动态代理
        CGLIB是第三方提供的动态代理的实现工具,不管有没有接口都可以实现动态代理。
        CGLIB实现动态代理的原理是 生成的动态代理是被代理者的子类,所以代理者具有和父类即被代理者 相同的方法,从而实现代理。
        
        a. 导入CGLIB相关包
            之前导入的spring包中就包含了CGLIB
                spring-core-3.2.3.RELEASE.jar
        b. 开发CGLIB程序
            案例:

  package cn.tedu.cglibproxy;
import java.lang.reflect.Method;
import org.junit.Test;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy; public class CglibProxyTest {
@Test
public void test01(){
final FBB fbb = new FBB(); //增强器
Enhancer enhancer = new Enhancer(); //设定接口 -- 此方法要求生成的动态代理额外实现指定接口们 ,单cglib动态代理不是靠接口实现的,所以可以不设置
enhancer.setInterfaces(fbb.getClass().getInterfaces()); //设定父类 -- 此处要传入被代理者的类,cglib是通过集成被代理者的类来持有和被代理者相同的方法的,此方法必须设置
enhancer.setSuperclass(fbb.getClass()); //设定回调函数 -- 为增强器设定回调函数,之后通过增强器生成的代理对象调用任何方法都会走到此回调函数中,实现调用真正被代理对象的方法的效果
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
if("拍电影".equals(method.getName())){
System.out.println("对不起,不拍了~~~");
return null;
}else{
System.out.println("检查权限。。。");
Object returnObj = method.invoke(fbb, args);
System.out.println("记录日志。。。");
return returnObj;
}
}
}); //生成代理对象
FBB proxy = (FBB) enhancer.create();
proxy.吃();
proxy.唱歌();
proxy.拍电影();
}
}

CGLIB动态代理原理图:

CGLIB动态代理的特点:
                优点:无论是否有接口都可以实现动态代理,使用场景基本不受限
        缺点:第三方提供的动态代理机制,不是原生的,需要导入第三方开发包才可以使用。

Spring知识点总结(四)之SpringAOP基础 - 代理设计模式的更多相关文章

  1. Spring知识点总结(四)之SpringAOP基础

        1. Spring aop中的基本概念        • 连接点(Joinpoint):在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候.在Spring AOP中,一个连接 ...

  2. JAVA-Spring AOP基础 - 代理设计模式

    利用IOC DI实现软件分层,虽然解决了耦合问题,但是很多地方仍然存在非该层应该实现的功能,造成了无法“高内聚”的现象,同时存在大量重复的代码,开发效率低下. @Service public clas ...

  3. Spring学习笔记四:SpringAOP的使用

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6776247.html  一:AOP基础概念 (1)通知(增强)Advice 通知,其实就是我们从众多类中提取出 ...

  4. Spring学习(四)—— java动态代理(JDK和cglib)

    JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他 的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托 ...

  5. Spring知识点小结(四)

    一.JdbcTemplate(jdbc模版--抽取的工具) web阶段DBUtils:        QueryRunner runner = new QueryRunner(dataSource); ...

  6. spring cloud系列教程第四篇-Eureka基础知识

    通过前三篇文章学习,我们搭建好了两个微服务工程.即:order80和payment8001这两个服务.有了这两个基础的框架之后,我们将要开始往里面添加东西了.还记得分布式架构的几个维度吗?我们要通过一 ...

  7. Spring源码系列(三)--spring-aop的基础组件、架构和使用

    简介 前面已经讲完 spring-bean( 详见Spring ),这篇博客开始攻克 Spring 的另一个重要模块--spring-aop. spring-aop 可以实现动态代理(底层是使用 JD ...

  8. Java基础知识点(四)

    前言:记录Java基础知识点,方便熟悉与掌握. 1.面向对象的"六原则一法则" “六原则一法则”:单一职责原则.开闭原则.依赖倒转原则.里氏替换原则.接口隔离原则.合成聚合复用原则 ...

  9. springAOP之代理模式

    springAOP指的是在spring中的AOP,什么是AOP,相对于java中的面向对象(oop),在面向对象中一些公共的行为,像日志记录,权限验证等如果都使用面向对象来做,会在每个业务方法中都写上 ...

随机推荐

  1. nyoj 1192——Salvation——————【搜索】

    Salvation 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 神秘瀑布镇是一个神秘的地方,那里有吸血鬼,狼人,巫师,二重身. Klaus(吸血鬼祖先) 为了利用 ...

  2. JS之this那些事

    一直以来,对this的讨论都是热门话题.有人说掌握了this就掌握了JavaScript的80%,说法有点夸张,但可见this的重要性.至今记录了很多关于this的零碎笔记,今天就来个小结. 本人看过 ...

  3. JavaScript基础(String)

    字符串 String 1.连接字符串 数字与字符串相加,为字符串 9+"9"; 2.字符串的长度 "abc".length; 3.从字符串中获取单个字符(索引下 ...

  4. 使用Spring的AOP实现切面日志

    AOP切面日志的使用方式 @Aspect @Component public class HttpAspect { private static final Logger logger = Logge ...

  5. JavaScript(Two)

    innerHtml xx.innerHtml 读取元素内的所有Html内容 xx.innerHtml = 新的值 替换元素内的所有Html内容 JS中不予许出现"-"; font- ...

  6. App Inventor 网络资源及推荐书目

    Ai2服务器 官方服务器:http://ai2.appinventor.edu/ 官方备用服务器:(大陆可用):http://contest.appinventor.mit.edu/ 国内个人服务器: ...

  7. Js 对象数组,转化为字符串

    var str = [{"cuid":"23910","content":"是","type":&q ...

  8. 【NLP_Stanford课堂】正则表达式

    或者 [Ww]oods,方括号里的是或的关系,符合其一即被提出.用来匹配单个字符 [A-Z]:表示所有的大写字母之一 [a-z]:表示所有的小写字母之一 [0-9]:表示所有的0-9的数字之一 否定: ...

  9. (四)svn 服务器端的使用之创建工程目录

    仓库中存放开发项目代码.文档等,需要创建一个工程目录. 在之前创建的仓库中右键点击: 创建成功 trunk:项目开发代码的主体,是从项目开始直到当前都处于活动的状态,从这里可以获得项目最新的源代码以及 ...

  10. 关于git stash的应用总结

    Step1 新增 git stash save -a "message" // 对于在项目里加入了代码新文件的开发来说,-a选项才会将新加入的代码文件同时放入暂存区 类似于 git ...