zoukankan      html  css  js  c++  java
  • 实现aop: 动态代理和cglib

    *****

    1,动态代理

    public interface UserDao {
        void save();
    }
    
    public class UserDaoImpl implements UserDao {
    
        private String name;
        
        public void save() {
            System.out.println("save() is called, name: "+name);
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        
    }

    代理工厂

    ProxyFactory.java

    package com.maple.util;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    import com.maple.dao.UserDao;
    import com.maple.dao.impl.UserDaoImpl;
    
    public class ProxyFactory implements InvocationHandler {
    
        private Object target;
        
        public Object createUserDao(Object target){
            this.target=target;
            return Proxy.newProxyInstance(this.target.getClass().getClassLoader(),
                            this.target.getClass().getInterfaces(), this);
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            System.out.println(proxy.getClass().getName());
            Object result=null;
            UserDaoImpl userDao=(UserDaoImpl)this.target;
            if(userDao.getName()!=null){
                result=method.invoke(userDao, args);
            }else{
                System.out.println("the name is null");
            }
            return result;
        }
    
    }

    测试

    @Test
        public void test() {
            ProxyFactory pf=new ProxyFactory();
            UserDaoImpl u=new UserDaoImpl();
            u.setName("maple");
            UserDao userDao=(UserDao) pf.createUserDao(u);
            userDao.save();
        }

    输出

    $Proxy5
    save() is called, name: maple

    2,cglib

    UserDaoImpl2.java不实现接口

    package com.maple.dao.impl;
    
    
    public class UserDaoImpl2{
    
        private String name;
        
        public void save() throws InterruptedException {
            Thread.sleep(3000);
            System.out.println("save() is called, name: "+name);
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
        public void raiseException(){
            throw new RuntimeException("this is test");
        }
        
    }

    CglibFactory.java

    package com.maple.util;
    
    import java.lang.reflect.Method;
    
    import com.maple.dao.impl.UserDaoImpl2;
    
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    public class CglibFactory implements MethodInterceptor {
    
        private Object target;
        public Object createUserDao(Object target){
            this.target=target;
            Enhancer enhancer=new Enhancer();
            enhancer.setSuperclass(target.getClass());
            enhancer.setCallback(this);
            return enhancer.create();
        }
        
        @Override
        public Object intercept(Object proxy, Method method, Object[] args,
                MethodProxy methodProxy) throws Throwable {
            UserDaoImpl2 userDao=(UserDaoImpl2)target;
            System.out.println("begin");
            if(userDao.getName()!=null){
                method.invoke(target, args);
            }else{
                System.out.println("the name is null");
            }
            System.out.println("end");
            return null;
        }
    
    }

    测试代码:

    @Test
        public void test2() throws InterruptedException{
            CglibFactory cf=new CglibFactory();
            UserDaoImpl2 temp=new UserDaoImpl2();
            UserDaoImpl2 userDao=(UserDaoImpl2)cf.createUserDao(temp);
            userDao.save();
            temp.setName("aa");
            userDao=(UserDaoImpl2)cf.createUserDao(temp);
            userDao.save();
        }

    结果:

    begin
    the name is null
    end
    begin
    save() is called, name: aa
    end

    3,spring综合了动态代理和cglib

    UserDaoImpl,java,UserDaoImpl2.java同上

    定义一个切面类MyInterceptor.java

    package com.maple.util;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    
    @Aspect
    public class MyInterceptor {
        //返回值任意,该包下面的所有类的所有方法,方法的参数个数任意
        @Pointcut("execution ( * com.maple.dao.impl.*.*(..))")
        public void anyMethod(){}
        
        @Before("anyMethod()")//执行符合切点的方法前执行
        public void before(){
            System.out.println("before()");
        }
        
        @After("anyMethod()")
        public void after(){
            System.out.println("after()");
        }
        
        @Around("anyMethod()")
        public void Around(ProceedingJoinPoint pjp) throws Throwable{
            long start=System.currentTimeMillis();
            System.out.println("begin around()");
            pjp.proceed();
            System.out.println("end around()");
            long end=System.currentTimeMillis();
            System.out.println("the time is "+(end-start));
        }
        @Before("anyMethod() && args(name)")
        public void before(String name){
            System.out.println("before(name): the name is:"+name);
        }
        
        @AfterReturning(pointcut="anyMethod()",returning="result")
        public void afterReturning(String result){
            System.out.println("the result is "+result);
        }
        
        @AfterThrowing(pointcut="anyMethod()",throwing="e")
        public void afterThrowing(Exception e){
            e.printStackTrace();
        }
        
    }

    测试

    @Test
        public void test3() throws InterruptedException{
            ApplicationContext context=new ClassPathXmlApplicationContext("/beans.xml");
            UserDao userDao=(UserDao) context.getBean("userDaoImpl");
            //userDao.save();
            UserDaoImpl2 userDao2=(UserDaoImpl2) context.getBean("userDaoImpl2");
            //userDao2.save();
            userDao2.setName("hhh");
            //userDao2.raiseException();
            //System.out.println(userDao2.getName());
        
        }

    在spring的配置文件beans.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"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-2.5.xsd           
               http://www.springframework.org/schema/aop
               http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
               http://www.springframework.org/schema/tx 
               http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context-2.5.xsd">
            <aop:aspectj-autoproxy/> <!-- spring打开aop功能 -->
            <bean id="userDaoImpl" class="com.maple.dao.impl.UserDaoImpl"/>
            <bean id="userDaoImpl2" class="com.maple.dao.impl.UserDaoImpl2"/>
            <bean id="myInterceptor444" class="com.maple.util.MyInterceptor"/>
            
            
    </beans>

    结果:

    before()
    before(name): the name is:hhh
    begin around()
    after()
    end around()
    the time is 0
    the result is null

    如果留下userDao2.save(),其他调用注释,则结果如下:

    before()
    begin around()
    save() is called, name: null
    after()
    end around()
    the time is 1
    the result is null

    注:1,在配置文件中如果没有对切面类的bean的定义,则不会执行切面类中的那些方法如before(),??

    2,2个before方法都执行了,然后around开始,执行方法,执行after,around结束,执行afterReturning()

    *****

    有问题在公众号【清汤袭人】找我,时常冒出各种傻问题,然一通百通,其乐无穷,一起探讨


  • 相关阅读:
    给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
    11
    实战 迁移学习 VGG19、ResNet50、InceptionV3 实践 猫狗大战 问题
    tx2系统备份与恢复
    如何在Ubuntu 18.04上安装和卸载TeamViewer
    bzoj 3732 Network (kruskal重构树)
    bzoj2152 聪聪可可 (树形dp)
    牛客 216D 消消乐 (二分图最小点覆盖)
    牛客 197E 01串
    Wannafly挑战赛23
  • 原文地址:https://www.cnblogs.com/qingmaple/p/4124784.html
Copyright © 2011-2022 走看看