Spring aop学习

1.jdk动态代理

package com.jhuc.aop;

import java.lang.reflect.Proxy;


public class Test {
   public static void main(String[] args) {
       AService aa=(AService) Proxy.newProxyInstance(AService.class.getClassLoader(), new Class[]{AService.class}, new ProxyA(new AServiceImpl()));
       aa.fooA("aha");
}
}

 

package com.jhuc.aop;

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

public class ProxyA implements InvocationHandler{
    private Object obj;
    
    public ProxyA(Object obj) {
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return method.invoke(obj, args);
    }


}

 

package com.jhuc.aop;

public interface AService {
    public void barA(); 

    public void fooA(String _msg);
}

 java动态代理就是生成一个类来实现接口,然后里面有一个对象引用handler。

 

2.cglib动态代理

package com.jhuc.aop;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor{
    Enhancer enhancer = new Enhancer();
    public <T> Object getProxy(Class<T> clazz) {
        //设置需要创建的子类
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        //通过字节码技术动态创建子类实例
        return enhancer.create();
    }
   
    @Override
    public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable{
          System.out.println("haha");
                return arg3.invokeSuper(arg0, arg2);
            
       
    }

}

 

package com.jhuc.aop;

import java.lang.reflect.Proxy;


public class Test {
   public static void main(String[] args) {
       AService aa=(AService) Proxy.newProxyInstance(AService.class.getClassLoader(), new Class[]{AService.class}, new ProxyA(new AServiceImpl()));
       aa.fooA("aha");
       CglibProxy proxy = new CglibProxy();
       AService bn=(AServiceImpl) proxy.getProxy(AServiceImpl.class);
       //通过动态生成子类的方式创建代理类
       bn.fooA("nimei");
}
}

 cglib是创建一个子类去实现这个类,覆盖父类方法

 

3.Spring aop

 测试代码

aopbean.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:dubbo="http://code.alibabatech.com/schema/dubbo"
	xmlns:aop="http://www.springframework.org/schema/aop"  
    xmlns:context="http://www.springframework.org/schema/context"  
    xmlns:tx="http://www.springframework.org/schema/tx" 
	xsi:schemaLocation="http://www.springframework.org/schema/beans  
		http://www.springframework.org/schema/beans/spring-beans.xsd  
		http://code.alibabatech.com/schema/dubbo  
		http://code.alibabatech.com/schema/dubbo/dubbo.xsd 
		 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd  
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd  
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
	<aop:config>  
        <aop:aspect id="TestAspect" ref="aspectBean">  
            <!--配置com.spring.service包下所有类或接口的所有方法-->  
            <aop:pointcut id="businessService" expression="execution(* com.jhuc.aop.*.*(..))" />  
            <aop:before pointcut-ref="businessService" method="doBefore"/>  
            <aop:after pointcut-ref="businessService" method="doAfter"/>  
            <aop:around pointcut-ref="businessService" method="doAround"/>  
            <aop:after-throwing pointcut-ref="businessService" method="doThrowing" throwing="ex"/> 
        </aop:aspect>  
    </aop:config>  
      
    <bean id="aspectBean" class="com.jhuc.aop.TestAspect" />  
    <bean id="aService" class="com.jhuc.aop.AServiceImpl"></bean>  
    <!-- <bean id="bService" class="com.jhuc.aop.BServiceImpl"></bean>  -->
</beans> 
	

 

package com.jhuc.aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainTest {
    public static void main(String[] args) throws Exception {
        ApplicationContext context = new ClassPathXmlApplicationContext("aopbean.xml");
        AService obj = (AService) context.getBean("aService");
        obj.fooA("ggg");
}
}

 

package com.jhuc.aop;
import org.aspectj.lang.JoinPoint;  
import org.aspectj.lang.ProceedingJoinPoint;  
public class TestAspect {  
    public TestAspect(){
        System.out.println("创建TestAspect实例");
    }
    
   ////后置通知:在目标方法之后(无论是否发生异常),执行的通知,
    public void doAfter(JoinPoint jp) { 
        
        System.out.println("doAfter 被调用: " + jp.getTarget().getClass().getName() + "." + jp.getSignature().getName());  
    }  
  //坏绕通知:需要携带ProceedingJoinPoint类型的参数
    //环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法
    //且环绕通知必须有返回值,返回值即目标方法的返回值。
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {  
        System.out.println("doAround 被调用");
        long time = System.currentTimeMillis();  
        Object retVal = pjp.proceed();  
        time = System.currentTimeMillis() - time;  
       
        return retVal;  
    }  
   ////声明该方法是一个前置通知:在目标方法开始之前执行
    public void doBefore(JoinPoint jp) {  
        System.out.println("doBefore 被调用: " + jp.getTarget().getClass().getName() + "." + jp.getSignature().getName());  
    }  
  //在目标方法出现异常时会执行的代码,
   //可以访问到异常对象,且可以指定在出现特定异常时在执行通知代码
  //如下面Exception ex,若是指定为NullpointerException ex就不会执行通知代码
    public void doThrowing(JoinPoint jp, Exception ex) {  
        System.out.println("doThrowing 被调用 " + jp.getTarget().getClass().getName() + "." + jp.getSignature().getName() + " throw exception");  
    }  
}  

 

package com.jhuc.aop;

public class AServiceImpl implements AService {  

 public void barA() {  
     System.out.println("AServiceImpl.barA()");  
 }  

 public void fooA(String _msg) throws Exception {  
     System.out.println("AServiceImpl.fooA(msg:" + _msg + ")");
     throw new Exception();
 }
}

 源码分析:

 1.首先在AbstractApplicationContext的refresh方法中的registerBeanPostProcessors(beanFactory)(注册后置处理器方法)中注册一个AspectJAwareAdvisorAutoProxyCreator后置处理器

2.AspectJAwareAdvisorAutoProxyCreator继承了AbstractAutoProxyCreator,AbstractAutoProxyCreator实现了BeanPostProcessor接口,在调用postProcessAfterInitialization方法时



 

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (!this.earlyProxyReferences.containsKey(cacheKey)) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (beanName != null && this.targetSourcedBeans.containsKey(beanName)) {
			return bean;
		}
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice.
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
                  //创建代理类
			Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

 

 

1.如果一个bean被配置了aop通知拦截,在生成这个bean的实例是生成一个代理类,里面记录了通知类信息

2.接下来重点看JdkDynamicAopProxy 的invoke方法了

猜你喜欢

转载自cainiaoboke.iteye.com/blog/2328231