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()

    *****

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


  • 相关阅读:
    yii框架_用户登录
    判断变量是否定义
    ajax小结
    yii框架_1
    yii框架_1_简单模型搭建与应用
    Greedy Gift Givers
    C# 音量控制 静音 等
    Fidelity Job Opportunities
    SPSiteDataQuery
    eBooks on html javascript & css
  • 原文地址:https://www.cnblogs.com/qingmaple/p/4124784.html
Copyright © 2011-2022 走看看