1,动态代理,指的是通过一个代理对象创建需要的业务对象,然后在这个代理对象中统一进行各种操作。

步骤:

1)写一个类实现InvocationHandler接口;

2)创建要代理的对象

2,创建一个简单的打印日志的类Logger

package com.yangw.spring.proxy;

import java.util.Date;

public class Logger {

    public static void info(String msg){
        System.out.println(new Date()+"----"+msg);
    }
}

3,自定义注解类

package com.yangw.spring.model;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface LogInfo {

    public String value() default "";

}

4,自定义动态代理类LogProxy

package com.yangw.spring.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import com.yangw.spring.model.LogInfo;
/**
 * 1 写一个类,实现InvocationHandler接口
 * @author Administrator
 *
 */
public class LogProxy implements InvocationHandler {
    //2,创建代理对象
    private Object target;
    private LogProxy(){};

    //3,创建一个方法来生成代理对象,这个方法的参数是要代理的对象
    public static Object getInstance(Object obj){
        //3.1  创建LogProxy对象
        LogProxy proxy=new LogProxy();
        //3.2 设置代理对象
        proxy.target=obj;
        //3.3 通过Proxy.newProxyInstance()创建代理对象
        //参数1:要代理对象的classloader,参数2:要代理对象的实现的所有接口,
        //参数3:实现InvocationHandler接口的对象
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
                obj.getClass().getInterfaces(), proxy);

    }
    /**
     * 当有了代理对象之后,都会调用下面的invoke()方法
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        //这里怎么处理完全由我们来控制的
        /*if(method.getName().equals("add")|| method.getName().equals("delete")){
            Logger.info("调用我...");
        }*/
        //只对有LogInfo注解的进行处理,
        //而且是在method.invoke调用之前,调用之后执行都可以
        //在异常中进行处理也可以
        if(method.isAnnotationPresent(LogInfo.class)){
            Logger.info(method.getAnnotation(LogInfo.class).value());
        }
            return method.invoke(target, args);
        //aspect orient program (面向切面编程)
    }

}

5,在需要加入注解的接口上面加入自定义注解LogInfo

package com.yangw.spring.dao;

import com.yangw.spring.model.LogInfo;
import com.yangw.spring.model.User;

public interface IUserDao {

    @LogInfo("add a user")
    public void add(User user) ;

    @LogInfo("delete a user")
    public void delete(int id) ;

    public User load(int id);
}

6,beans2.xml中的配置如下

<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"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.0.xsd">

   <!--1, 打开Spring的annotation -->
   <context:annotation-config/>
   <!-- 2, 设定Spring去那些包中找annotation -->
    <context:component-scan base-package="com.yangw.spring" />

    <!--用代理类实现
        对于静态(static)的注入,使用factory-method
    -->
    <bean id="userDynamicDao" class="com.yangw.spring.proxy.LogProxy"
          factory-method="getInstance">
        <!--静态方法传入的参数 -->
        <constructor-arg ref="userDao" />
    </bean>
    <!-- 依次加入想加入的
    <bean id="msgDynamicDao" class="com.yangw.spring.proxy.LogProxy"
          factory-method="getInstance">
        <constructor-arg ref="MsgDao" />
    </bean>
    -->
</beans>

7,UserService类上注入userDynamicDao

package com.yangw.spring.service;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.yangw.spring.dao.IUserDao;
import com.yangw.spring.model.User;
@Service("userService")
public class UserService implements IUserService {

    @Resource(name="userDynamicDao")
    private IUserDao userDao ;

    @Override
    public void add(User user) {

        userDao.add(user);

    }

    @Override
    public void delete(int id) {

        userDao.delete(id);
    }

    @Override
    public User load(int id) {

        return    userDao.load(id);

    }

}

7, 测试

package com.yangw.spring.test;

import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.yangw.spring.action.UserAction;
import com.yangw.spring.model.User;

public class TestSpring {

     //1,创建Spring工厂
    BeanFactory factory= new ClassPathXmlApplicationContext("beans2.xml");

    @Test
    public void testUser(){

        //2,通过工厂获取Spring的对象
        UserAction userAction = factory.getBean("userAction", UserAction.class);

        User u1=new User(1,"yangw");
        userAction.setUser(u1);
        userAction.add();
        userAction.delete();
        userAction.load();
    }
}

8, Spring实现动态代理(基于annotation方式)

导入aopalliance-1.0.jar aspectjrt-1.6.10.jar aspectjweaver-1.7.2.jar 三个包,Spring使用这三个包实现AOP

<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-3.0.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop.xsd">

   <!--1, 打开Spring的annotation -->
   <context:annotation-config/>
   <!-- 2, 设定Spring去那些包中找annotation -->
   <context:component-scan base-package="com.yangw.spring" />

   <!-- 打开基于annotation的aop自动代理 -->
   <aop:aspectj-autoproxy />
</beans>

切面类

package com.yangw.spring.proxy;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Component("logAspect") //交给Spring管理
@Aspect //说明是一个切面类
public class LogAspect {

    //前置通知
    // 第1个"*": 任意返回值
    // 第2个"*": com.yangw.spring.dao包中的所有类
    // 第3个"*": add*表示以add开头的所有方法
    // "(..)"  : 表示方法参数是任意值
    // "||"    : 可以用或表达式加入多个条件
    /**
     * 函数调用之前执行
     */
    @Before("execution(* com.yangw.spring.dao.*.add*(..))||"
            +"execution(* com.yangw.spring.dao.*.delete*(..))||"
            +"execution(* com.yangw.spring.dao.*.update*(..))")
    public void logStart(JoinPoint jp){
        System.out.println(jp.getTarget()); //得到执行的类
        System.out.println(jp.getSignature().getName()); //得到执行的方法名
        Logger.info("log start.");
    }
    /**
     * 函数调用之后执行
     */
    @After("execution(* com.yangw.spring.dao.*.add*(..))||"
            +"execution(* com.yangw.spring.dao.*.delete*(..))||"
            +"execution(* com.yangw.spring.dao.*.update*(..))")
    public void logEnd(JoinPoint jp){
        System.out.println(jp.getTarget()); //得到执行的类
        System.out.println(jp.getSignature().getName()); //得到执行的方法名
        Logger.info("log end.");
    }

    /**
     * 函数调用过程中执行
     */
    @Around("execution(* com.yangw.spring.dao.*.add*(..))||"
            +"execution(* com.yangw.spring.dao.*.delete*(..))||"
            +"execution(* com.yangw.spring.dao.*.update*(..))")
    public void logAround(ProceedingJoinPoint pjp) throws Throwable{

        Logger.info("log around start");
        pjp.proceed(); //让程序往下执行
        Logger.info("log around end.");
    }
}

测试

package com.yangw.spring.test;

import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.yangw.spring.action.UserAction;
import com.yangw.spring.model.User;

public class TestSpring {

     //1,创建Spring工厂
    BeanFactory factory= new ClassPathXmlApplicationContext("beans3.xml");

    @Test
    public void testUser(){

        //2,通过工厂获取Spring的对象
        UserAction userAction = factory.getBean("userAction", UserAction.class);

        User u1=new User(1,"yangw");
        userAction.setUser(u1);
        userAction.add();
        userAction.delete();
        userAction.load();
    }
}

测试结果

Mon Oct 21 19:13:29 CST 2013----log around start
com.yangw.spring.dao.UserDao@18ce14a
add
Mon Oct 21 19:13:29 CST 2013----log start.
add :User [id=1, username=yangw]
Mon Oct 21 19:13:29 CST 2013----log around end.
com.yangw.spring.dao.UserDao@18ce14a
add
Mon Oct 21 19:13:29 CST 2013----log end.
Mon Oct 21 19:13:29 CST 2013----log around start
com.yangw.spring.dao.UserDao@18ce14a
delete
Mon Oct 21 19:13:29 CST 2013----log start.
delete :0
Mon Oct 21 19:13:29 CST 2013----log around end.
com.yangw.spring.dao.UserDao@18ce14a
delete
Mon Oct 21 19:13:29 CST 2013----log end.
load :0
null

9, Spring实现动态代理(基于xml方式) 一般这种用的多

导入aopalliance-1.0.jar aspectjrt-1.6.10.jar aspectjweaver-1.7.2.jar 三个包,Spring使用这三个包实现AOP

<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-3.0.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop.xsd">

   <!--1, 打开Spring的annotation -->
   <context:annotation-config/>
   <!-- 2, 设定Spring去那些包中找annotation -->
   <context:component-scan base-package="com.yangw.spring" />

   <aop:config>
       <!-- 定义切面 -->
       <aop:aspect id="myLogAspect" ref="logAspect">
           <!-- 在哪些位置加入相应的Aspect-->
           <aop:pointcut id="logPointCut" expression="execution(* com.yangw.spring.dao.*.add*(..))||
                   execution(* com.yangw.spring.dao.*.delete*(..))||
                   execution(* com.yangw.spring.dao.*.update*(..))" />
           <!-- 定义通知 -->
           <aop:before method="logStart" pointcut-ref="logPointCut"/>
           <aop:after method="logEnd" pointcut-ref="logPointCut"/>
           <aop:around method="logAround" pointcut-ref="logPointCut"/>
       </aop:aspect>

   </aop:config>
</beans>
package com.yangw.spring.proxy;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;

@Component("logAspect") //交给Spring管理

public class LogAspect1 {

    public void logStart(JoinPoint jp){
        System.out.println(jp.getTarget()); //得到执行的类
        System.out.println(jp.getSignature().getName()); //得到执行的方法名
        Logger.info("log start.");
    }

    public void logEnd(JoinPoint jp){
        System.out.println(jp.getTarget()); //得到执行的类
        System.out.println(jp.getSignature().getName()); //得到执行的方法名
        Logger.info("log end.");
    }

    public void logAround(ProceedingJoinPoint pjp) throws Throwable{

        Logger.info("log around start");
        pjp.proceed(); //让程序往下执行
        Logger.info("log around end.");
    }
}

测试和结果与前面的基于annotation的一模一样,不在赘述!

Spring02-AOP的更多相关文章

  1. JAVAEE——spring02:使用注解配置spring、sts插件、junit整合测试和aop演示

    一.使用注解配置spring 1.步骤 1.1 导包4+2+spring-aop 1.2 为主配置文件引入新的命名空间(约束) 1.3 开启使用注解代替配置文件 1.4 在类中使用注解完成配置 2.将 ...

  2. Spring第二天——IOC注解操作与AOP概念

    大致内容 spring的bean管理(注解实现) AOP原理 log4j介绍 spring整合web项目的演示 一.spring注解实现bean管理 注解: 代码中一些特殊的标记,使用注解也可以完成一 ...

  3. spring-02

    spring-02 1.谈谈你对 Spring 的理解 Spring 是一个开源框架,为简化企业级应用开发而生.Spring 可以是使简单的 JavaBean 实现以前只有 EJB 才能实现的功能.S ...

  4. Spring03——有关于 Spring AOP 的总结

    本文将为各位带来 Spring 的另一个重点知识点 -- Spring AOP.关注我的公众号「Java面典」,每天 10:24 和你一起了解更多 Java 相关知识点. 什么是 AOP 面向切面编程 ...

  5. 基于spring注解AOP的异常处理

    一.前言 项目刚刚开发的时候,并没有做好充足的准备.开发到一定程度的时候才会想到还有一些问题没有解决.就比如今天我要说的一个问题:异常的处理.写程序的时候一般都会通过try...catch...fin ...

  6. Spring基于AOP的事务管理

                                  Spring基于AOP的事务管理 事务 事务是一系列动作,这一系列动作综合在一起组成一个完整的工作单元,如果有任何一个动作执行失败,那么事务 ...

  7. 学习AOP之透过Spring的Ioc理解Advisor

    花了几天时间来学习Spring,突然明白一个问题,就是看书不能让人理解Spring,一方面要结合使用场景,另一方面要阅读源代码,这种方式理解起来事半功倍.那看书有什么用呢?主要还是扩展视野,毕竟书是别 ...

  8. 学习AOP之深入一点Spring Aop

    上一篇<学习AOP之认识一下SpringAOP>中大体的了解了代理.动态代理及SpringAop的知识.因为写的篇幅长了点所以还是再写一篇吧.接下来开始深入一点Spring aop的一些实 ...

  9. 学习AOP之认识一下Spring AOP

    心碎之事 要说知道AOP这个词倒是很久很久以前了,但是直到今天我也不敢说非常的理解它,其中的各种概念即抽象又太拗口. 在几次面试中都被问及AOP,但是真的没有答上来,或者都在面上,这给面试官的感觉就是 ...

  10. .Net中的AOP系列之构建一个汽车租赁应用

    返回<.Net中的AOP>系列学习总目录 本篇目录 开始一个新项目 没有AOP的生活 变更的代价 使用AOP重构 本系列的源码本人已托管于Coding上:点击查看. 本系列的实验环境:VS ...

随机推荐

  1. 如何修改ionic Popup的样式

    第一次用ionic的Popup时感觉很好用,但是太丑了.但是又不会修改自定义的样式,只能自己写了个模态框.后来仔细搜索了一下.发现还是可以修改的. var confirmPopup = $ionicP ...

  2. quartz学习笔记(一)简单入门

    前言 quartz是Java编写的一款开源的任务调度开发框架,在项目开发中很多场景都可以用到,比如订单超期自动收货. 所谓程序源于生活,生活中也有很多场景可以用quartz来模拟,比如工作日早上七点起 ...

  3. Linux 修改用户名

    0.使用root用户登录进行操作 1.删除用户相关进程 ps -ef | grep zheng236 2. 修改用户登录名 usermod zheng236 -l zheng 3.修改用户家目录 mv ...

  4. BotVS趋势交易策略-MACD

    MACD低买高卖自动跟单滑动止损策略 , 基于Python实现. 交叉后前一柱指金叉后的第一柱的值, 交叉后前一柱指金叉前的最后一个柱的值, 滑动价格指下单时加的价格,比如买单会现价加上这个价格,卖单 ...

  5. spring boot / cloud (七) 使用@Retryable来进行重处理

    spring boot / cloud (七) 使用@Retryable来进行重处理 前言 什么时候需要重处理? 在实际工作中,重处理是一个非常常见的场景,比如:发送消息失败,调用远程服务失败,争抢锁 ...

  6. Android笔记: 实现手机震动效果

    1.震动是系统的服务,首先需添加震动权限 <uses-permission android:name="android.permission.VIBRATE" /> 2 ...

  7. Spring集成RabbitMQ-必须知道的几个概念

    上篇<Spring集成RabbiMQ-Spring AMQP新特性>我们了解了最新spring-rabbit的2.0.0.M5版本相较于之前有哪些变化.其实使用Spring-amqp确实简 ...

  8. 深入理解HTTP协议—HTTP协议详解(真的很经典)

    引言 HTTP是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展.目前在WWW中使用的是HTTP/1. ...

  9. 使用VMware Workstation安装win7镜像文件时遇见的错误

    最近打算使用虚拟机安装个系统玩玩,就去网站上找了教程安装下win7系统.但是在安装过程中遇见两个问题,现在把遇见的问题总结记录一下,以及解决方法罗列一下. 我当时使用的是VMware 12版的,系统是 ...

  10. R0~R16寄存器作用(转)

    R0-R3     用作传入函数参数,传出函数返回值.在子程序调用之间,可以将 r0-r3 用于任何用途. 被调用函数在返回之前不必恢复 r0-r3.如果调用函数需要再次使用 r0-r3 的内容,则它 ...