zoukankan      html  css  js  c++  java
  • Spring02-AOP

    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的一模一样,不在赘述!

    ----------- 赠人玫瑰,手有余香     如果本文对您有所帮助,动动手指扫一扫哟   么么哒 -----------


    未经作者 https://www.cnblogs.com/xin1006/ 梦相随1006 同意,不得擅自转载本文,否则后果自负
  • 相关阅读:
    作业5,6 2019/10/23
    作业1、2、3、4 2019/10/23
    实现Map传参Mybatis
    maven工程配置pom.xml实现mybatis的访问数据库操作
    测试
    Postman篇之命令行测试
    unittest框架
    测试
    测试
    测试
  • 原文地址:https://www.cnblogs.com/xin1006/p/3380209.html
Copyright © 2011-2022 走看看