Spring aop learning

1.jdk dynamic proxy

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;

AService public interface {
    public void barA();

    public void fooA(String _msg);
}

 Java dynamic proxy is to generate a class to implement the interface, and then there is an object reference handler in it.

 

2.cglib dynamic proxy

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) {
        //Set the subclass to be created
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        / / Dynamically create subclass instances through bytecode technology
        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);
       //Create a proxy class by dynamically generating subclasses
       bn.fooA("nimei");
}
}

 cglib is to create a subclass to implement this class and override the parent class method

 

3.Spring aop

 test code

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">  
            <!--Configure all methods of all classes or interfaces under the com.spring.service package-->  
            <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("Create TestAspect instance");
    }
    
   ////Post notification: After the target method (whether an exception occurs or not), the notification executed,
    public void doAfter(JoinPoint jp) {
        
        System.out.println("doAfter 被调用: " + jp.getTarget().getClass().getName() + "." + jp.getSignature().getName());  
    }  
  //Bad winding notification: need to carry parameters of type ProceedingJoinPoint
    // Surround notification is similar to the whole process of dynamic proxy: the parameter of type ProceedingJoinPoint can decide whether to execute the target method
    //And the surround notification must have a return value, which is the return value of the target method.
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {  
        System.out.println("doAround is called");
        long time = System.currentTimeMillis();  
        Object retVal = pjp.proceed();  
        time = System.currentTimeMillis() - time;  
       
        return retVal;  
    }  
   //// Declare the method as a pre-advice: execute before the target method starts
    public void doBefore(JoinPoint jp) {  
        System.out.println("doBefore 被调用: " + jp.getTarget().getClass().getName() + "." + jp.getSignature().getName());  
    }  
  //The code that will be executed when the target method fails,
   //The exception object can be accessed, and the notification code can be executed when a specific exception occurs
  //As the following Exception ex, if it is specified as NullpointerException ex, the notification code will not be executed
    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();
 }
}

 Source code analysis:

 1. First register an AspectJAwareAdvisorAutoProxyCreator post-processor in registerBeanPostProcessors(beanFactory) (registered post-processor method) in the refresh method of AbstractApplicationContext

2. AspectJAwareAdvisorAutoProxyCreator inherits AbstractAutoProxyCreator, AbstractAutoProxyCreator implements the BeanPostProcessor interface, when calling the postProcessAfterInitialization method



 

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);
                  //create proxy class
			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. If a bean is configured with aop notification interception, an instance of the bean is generated to generate a proxy class, which records the notification class information

2. Next, let's focus on the invoke method of JdkDynamicAopProxy

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=327041659&siteId=291194637