spring aop入门 和 代理模式的衔接

建议先看一下代理模式:https://blog.csdn.net/dengjili/article/details/82802614

在Spring AOP中,有 4 种类型通知(advices)的支持:

  • 通知(Advice)之前 - 该方法执行前运行
  • 通知(Advice)返回之后 – 运行后,该方法返回一个结果
  • 通知(Advice)抛出之后 – 运行方法抛出异常后,
  • 环绕通知 – 环绕方法执行运行,结合以上这三个通知。

下载相关代码,根据描述运行

相关代码
https://github.com/dengjili/springaop

先看一个spring 例子

被代理类

package priv.dengjl.springaop.service;

/**
 * 业务类
 * 
 * @author it
 */
public class TestService {
	private String name;
	private String url;

	public void setName(String name) {
		this.name = name;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public void printName() {
		System.out.println("名称 : " + this.name);
	}

	public void printURL() {
		System.out.println("网址 : " + this.url);
	}

	public void printThrowException() {
		throw new IllegalArgumentException();
	}
}

before动作

package priv.dengjl.springaop.aop;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class TestBeforeAdvice implements MethodBeforeAdvice
{
	@Override
	public void before(Method method, Object[] args, Object target)
		throws Throwable {
		System.out.println("前置通知【方法1】!!!,执行方法前");
	}
}

其他类似,后面给出工程代码

spring配置信息

applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

	<!-- 基础bean -->
	<bean id="testService" class="priv.dengjl.springaop.service.TestService">
		<property name="name" value="呵呵哒" />
		<property name="url" value="www.mmp.com" />
	</bean>

	<!-- 代理类bean -->
	<bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
		<!-- 被代理对象 -->
		<property name="target" ref="testService" />

		<!-- 配置被代理对象需要处理的动作 -->
		<property name="interceptorNames">
			<list>
				<value>testBeforeAdvice</value>
				<value>testBeforeAdvice2</value>
				<value>testAfterAdvice</value>
				<value>testAfterAdvice2</value>
				<value>testThrowException</value>
				<value>testAroundMethod</value>
			</list>
		</property>
	</bean>

	<bean id="testBeforeAdvice" class="priv.dengjl.springaop.aop.TestBeforeAdvice" />
	<bean id="testBeforeAdvice2" class="priv.dengjl.springaop.aop.TestBeforeAdvice2" />
	<bean id="testAfterAdvice" class="priv.dengjl.springaop.aop.TestAfterAdvice" />
	<bean id="testAfterAdvice2" class="priv.dengjl.springaop.aop.TestAfterAdvice2" />
	<bean id="testThrowException" class="priv.dengjl.springaop.aop.TestThrowException" />
	<bean id="testAroundMethod" class="priv.dengjl.springaop.aop.TestAroundMethod" />

</beans>

测试类

package priv.dengjl.springaop.service;

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

public class App 
{
    public static void main( String[] args )
    {
    	ApplicationContext appContext = new ClassPathXmlApplicationContext(
				new String[] { "applicationContext.xml" });

    	TestService cust = (TestService) appContext.getBean("serviceProxy");

		System.out.println("*************************");
		cust.printName();
		System.out.println("*************************");
		cust.printURL();
		System.out.println("*************************");
		try {
			cust.printThrowException();
		} catch (Exception e) {
			System.out.println("有异常发生");
			System.out.println("*************************");
		}
    }
}

测试结果

*************************
前置通知【方法1】!!!,执行方法前
前置通知【方法2】!!!,执行方法前
TestAroundMethod环绕 before
名称 : 呵呵哒
TestAroundMethod环绕 after
后置通知【方法2】!!!,执行方法后
后置通知【方法1】!!!,执行方法后
*************************
前置通知【方法1】!!!,执行方法前
前置通知【方法2】!!!,执行方法前
TestAroundMethod环绕 before
网址 : www.mmp.com
TestAroundMethod环绕 after
后置通知【方法2】!!!,执行方法后
后置通知【方法1】!!!,执行方法后
*************************
前置通知【方法1】!!!,执行方法前
前置通知【方法2】!!!,执行方法前
TestAroundMethod环绕 before
TestAroundMethod环绕 after异常
抛出异常后,处理!!!
有异常发生
*************************
配置信息讲解

配置映射关系

在这里插入图片描述

Advisor入门

配置文件applicationContextAdvisor.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

	<!-- 基础bean -->
	<bean id="testService" class="priv.dengjl.springaop.service.TestService">
		<property name="name" value="呵呵哒" />
		<property name="url" value="www.mmp.com" />
	</bean>
	
	<!-- 切入点,想拦截哪些方法,更加细粒度 -->
	<bean id="testPointcut" class="priv.dengjl.springaop.advisor.MyPointcut">
		<property name="addMappingName" value="printName"/>
	</bean>  
	
	<!-- 使用DefaultPointcutAdvisor -->
	<bean id="testAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">  
      <property name="pointcut">  
          <ref bean="testPointcut" />  
      </property>  
      <property name="advice">  
          <ref bean="testBeforeAdvice"/>  
      </property>  
    </bean>  
    
    <!-- 使用RegexpMethodPointcutAdvisor -->
    <bean id="regexpAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">  
      <property name="patterns">  
          <list>
          		<!-- 参考java pattern类正则表达式配置  这是匹配printURL方法 -->
          		<value>.*URL.*</value>
          </list> 
      </property>  
      <property name="advice">  
          <ref bean="testAfterAdvice"/>  
      </property>  
    </bean>  
    
    <!-- 使用NameMatchMethodPointcutAdvisor *完全匹配 -->
    <bean id="myAroundAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">    
      <property name="mappedNames">  
        <list>  
          <value>*ThrowException*</value>  
        </list>  
      </property>  
      <property name="advice">  
        <ref bean="testAroundMethod" />  
      </property>  
    </bean>  
	
	<!-- 代理类bean -->
	<bean id="serviceProxy" 
                 class="org.springframework.aop.framework.ProxyFactoryBean">
		<!-- 被代理对象 -->
		<property name="target" ref="testService" />

		<!-- 配置被代理对象需要处理的动作 -->
		<property name="interceptorNames">
			<list>
				<value>testAdvisor</value>
				<value>regexpAdvisor</value>
				<value>myAroundAdvisor</value>
			</list>
		</property>
	</bean>
	
	<bean id="testBeforeAdvice" class="priv.dengjl.springaop.aop.TestBeforeAdvice" />
	<bean id="testBeforeAdvice2" class="priv.dengjl.springaop.aop.TestBeforeAdvice2" />
	<bean id="testAfterAdvice" class="priv.dengjl.springaop.aop.TestAfterAdvice" />
	<bean id="testAfterAdvice2" class="priv.dengjl.springaop.aop.TestAfterAdvice2" />
	<bean id="testThrowException" class="priv.dengjl.springaop.aop.TestThrowException" />
	<bean id="testAroundMethod" class="priv.dengjl.springaop.aop.TestAroundMethod" />

</beans>

测试类

package priv.dengjl.springaop.service;

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

/**
 * Hello world!
 *
 */
public class AppAdvisor 
{
    public static void main( String[] args )
    {
    	ApplicationContext appContext = new ClassPathXmlApplicationContext(
				new String[] { "applicationContextAdvisor.xml" });

    	TestService cust = (TestService) appContext.getBean("serviceProxy");

		System.out.println("*************************");
		cust.printName();
		System.out.println("*************************");
		cust.printURL();
		System.out.println("*************************");
		try {
			cust.printThrowException();
		} catch (Exception e) {
			System.out.println("有异常发生");
			System.out.println("*************************");
		}
    }
}

测试结果
根据配置结果拦截

*************************
前置通知【方法1】!!!,执行方法前
名称 : 呵呵哒
*************************
网址 : www.mmp.com
后置通知【方法1】!!!,执行方法后
*************************
TestAroundMethod环绕 before
TestAroundMethod环绕 after异常
有异常发生
*************************

配置信息讲解

配置映射关系,最简单的方式

在这里插入图片描述

正则方式和名称
在这里插入图片描述

Spring自动代理创建者实例与动态代理

配置文件applicationContextAutoProxy.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

	<!-- 基础bean -->
	<bean id="testService" class="priv.dengjl.springaop.service.TestService">
		<property name="name" value="呵呵哒" />
		<property name="url" value="www.mmp.com" />
	</bean>
	
	<!-- 切入点,想拦截哪些方法,更加细粒度 -->
	<bean id="testPointcut" class="priv.dengjl.springaop.advisor.MyPointcut">
		<property name="addMappingName" value="printName"/>
	</bean>  
	
	<!-- 使用DefaultPointcutAdvisor -->
	<bean id="testAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">  
      <property name="pointcut">  
          <ref bean="testPointcut" />  
      </property>  
      <property name="advice">  
          <ref bean="testBeforeAdvice"/>  
      </property>  
    </bean>  
    
    <!-- 使用RegexpMethodPointcutAdvisor -->
    <bean id="regexpAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">  
      <property name="patterns">  
          <list>
          		<!-- 参考java pattern类正则表达式配置  这是匹配printURL方法 -->
          		<value>.*URL.*</value>
          </list> 
      </property>  
      <property name="advice">  
          <ref bean="testAfterAdvice"/>  
      </property>  
    </bean>  
    
    <!-- 使用NameMatchMethodPointcutAdvisor *完全匹配 -->
    <bean id="myAroundAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">    
      <property name="mappedNames">  
        <list>  
          <value>*ThrowException*</value>  
        </list>  
      </property>  
      <property name="advice">  
        <ref bean="testAroundMethod" />  
      </property>  
    </bean>  
	
	<!-- 静态代理类bean -->
	<!-- <bean id="serviceProxy" 
                 class="org.springframework.aop.framework.ProxyFactoryBean">
		被代理对象
		<property name="target" ref="testService" />

		配置被代理对象需要处理的动作
		<property name="interceptorNames">
			<list>
				<value>testAdvisor</value>
				<value>regexpAdvisor</value>
				<value>myAroundAdvisor</value>
			</list>
		</property>
	</bean> -->
	<!-- 动态代理类bean -->
	<!-- <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
        <property name="beanNames">
            <list>
                <value>*Service</value>
            </list>
        </property>
        <property name="interceptorNames">
            <list>
                <value>testAdvisor</value>
			    <value>regexpAdvisor</value>
				<value>myAroundAdvisor</value>
            </list>
        </property>
    </bean> -->
    
    <!-- DefaultAdvisorAutoProxyCreator 是非常强大的,如果有 bean 相关连,Spring会自动创建一个代理,不建议使用,应当显示说明 -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />
	
	<bean id="testBeforeAdvice" class="priv.dengjl.springaop.aop.TestBeforeAdvice" />
	<bean id="testBeforeAdvice2" class="priv.dengjl.springaop.aop.TestBeforeAdvice2" />
	<bean id="testAfterAdvice" class="priv.dengjl.springaop.aop.TestAfterAdvice" />
	<bean id="testAfterAdvice2" class="priv.dengjl.springaop.aop.TestAfterAdvice2" />
	<bean id="testThrowException" class="priv.dengjl.springaop.aop.TestThrowException" />
	<bean id="testAroundMethod" class="priv.dengjl.springaop.aop.TestAroundMethod" />

</beans>

测试类

package priv.dengjl.springaop.service;

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

/**
 * Hello world!
 *
 */
public class AppAutoProxy 
{
    public static void main( String[] args )
    {
    	ApplicationContext appContext = new ClassPathXmlApplicationContext(
				new String[] { "applicationContextAutoProxy.xml" });

    	TestService cust = (TestService) appContext.getBean("testService");

		System.out.println("*************************");
		cust.printName();
		System.out.println("*************************");
		cust.printURL();
		System.out.println("*************************");
		try {
			cust.printThrowException();
		} catch (Exception e) {
			System.out.println("有异常发生");
			System.out.println("*************************");
		}
    }
}
配置信息讲解

配置映射
在这里插入图片描述

相关代码

https://github.com/dengjili/springaop

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值