Spring编程---(二)---aop切面技术

Spring AOP编程(1)

    面向切面编程:Aspect Oriented Programming,可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。
      AOP可以说是OOP(面向对象编程)的补充和完善。在OOP设计中有可能导致代码的重复不利于模块的重用性,例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能关系不大。但是在OOP中这些业务要和核心业务代码在代码这一级集成。还有些如安全性、事务等也是如此。能不能把这些与核心业务无关但系统中需要使用的业务(称为切面)单独编写成一个模块,在主要核心业务代码中不调用,而是在配置文件中做些配置,配置核心业务需要使用到得切面部分,在系统编译时才织入到业务模块中。

Spring AOP编程(2)

    切面(Aspect):简单的理解就是把那些与核心业务无关的代码提取出来,进行封装成一个或几个模块用来处理那些附加的功能代码。(如日志,事务,安全验证)我们把这个模块的作用理解为一个切面,其实切面就是我们写一个类,这个类中的代码原来是在业务模块中完成的,现在单独成一个或几个类。在业务模块需要的时候才织入。
    连接点(Joinpoint):在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。 在Spring AOP中,一个连接点总是代表一个方法的执行。通过声明一个JoinPoint类型的参数可以使通知(Advice)的主体部分获得连接点信息。  
    切入点(Pointcut):本质上是一个捕获连接点的结构。在AOP中,可以定义一个pointcut,来捕获相关方法的调用

Spring AOP编程(3)

      织入(Weaving):把切面(aspect)连接到其它的应用程序类型或者对象上,并创建一个被通知(advised)的对象。 这些可以在编译时,类加载时和运行时完成。Spring和其它纯Java AOP框架一样,在运行时完成织入。 
      通知(Advice):在切面的某个特定的连接点(Joinpoint)上执行的动作。通知有各种类型,其中包括“around”、“before”和“after”等通知。 通知的类型将在后面部分进行讨论。许多AOP框架,包括Spring,都是以拦截器做通知模型,并维护一个以连接点为中心的拦截器链。

通知的类型: 
    前置通知(Before advice):在某连接点(join point)之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)。 
    返回后通知(After returning advice):在某连接点(join point)正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。 
    抛出异常后通知(After throwing advice):在方法抛出异常退出时执行的通知。
    后置通知(After (finally) advice):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。 
     环绕通知(Around Advice):包围一个连接点(join point)的通知,如方法调用。这是最强大的一种通知类型。 环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。

Spring AOP编程(5)

 

第1步: 编写一个类封装用户的常见操作。 UserDao.java
package com.aop;
public class UserDao {
   public void save(String name){
	     System.out.println("----save user----");
   }
   public void delete(){
	      System.out.println("----delete user----");
   }
   public void update(){
	  System.out.println("----update user----");
   }
 }

第2步: 编写一个检查用户是否合法的类。

package com.aop;
public class CheckSecurity {
    public void check(){ System.out.println("--check admin--");
    }
}

第3步: 改写Spring的配置文件

<bean id="checkbean" class="com.aop.CheckSecurity"></bean>
<bean id="userDao" class="com.aop.UserDao"/>
 <aop:config>
    <aop:aspect id="security" ref="checkbean">
       <aop:pointcut id="allAddMethod" expression=
                     "execution(* com.aop.UserDao.*(..))"/>
       <aop:before method="check" pointcut-ref= "allAddMethod"/>
    </aop:aspect>
</aop:config>

第4步:编写测试类 Test.java。

 

 

package com.aop;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.*;
public class Test {
     public static void main(String[] args) {
		 /* 读取Spring配置文件,创建一个Bean工厂 */
       BeanFactory factory = new 
      ClassPathXmlApplicationContext(“applicationContext.xml”);  
       UserDao dao = (UserDao) factory.getBean("userDao");
       dao.save("zhou");
	  }
}




下面出示我写的两个例子

 

例一:

Person.java

 

package cn.hncu.spring4.aop.demo3;

public class Person {
	public void run(){
		System.out.println("I'm running...");
	}
	public void run(int i){
		System.out.println("I'm running..."+i);
	}
	public void speak(){
		System.out.println("I'm speaking...");
	}
}

AopDemo.java

 

 

package cn.hncu.spring4.aop.demo3;

import java.lang.reflect.Method;

import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.junit.Test;
import org.springframework.aop.Advisor;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.JdkRegexpMethodPointcut;

public class AopDemo {
	@Test //纯Java的方式实现切面(拦截)技术
	public void demo1(){
		Person p=new Person();//被代理的原型对象
		ProxyFactory factory=new ProxyFactory();//该类的功能没有ProxyFactoryBean强
		factory.setTarget(p);//1、给代理工厂一个原型对象
		
		//切面 = 切点 + 通知
		//切点
		JdkRegexpMethodPointcut cut=new JdkRegexpMethodPointcut();
//		cut.setPattern("cn.hncu.spring4.aop.demo3.Person.run");
		cut.setPattern(".*run.*");//参数是正则表达式
		
		//通知
		Advice advice=new MethodInterceptor() {
			
			@Override
			public Object invoke(MethodInvocation methodInv) throws Throwable {
				System.out.println("前面拦");
				Object resObj=methodInv.proceed();
				System.out.println("后面拦");
				return resObj;
			}
		};
		
		//切面 = 切点 + 通知
		Advisor advisor=new DefaultPointcutAdvisor(cut, advice);
		factory.addAdvisor(advisor);//2 给代理工厂一个切面
		Person p2=(Person) factory.getProxy();
		p2.run();
		p2.run(6);
		p2.speak();//不会拦
	}
	
	@Test
	public void demo2(){
		Person p=new Person();//被代理的原型对象
		ProxyFactoryBean factory=new ProxyFactoryBean();
		factory.setTarget(p);//1、给代理工厂一个原型对象
		
		//切面 = 切点 + 通知
		//切点
		JdkRegexpMethodPointcut cut=new JdkRegexpMethodPointcut();
//		cut.setPattern("cn.hncu.spring4.aop.demo3.Person.run");
		cut.setPatterns(".*run.*",".*speak.*");//参数是正则表达式
		
		//通知  前切面---不需要放行,原方法也能执行
		Advice before=new MethodBeforeAdvice() {
			
			@Override
			public void before(Method arg0, Object[] arg1, Object arg2)
					throws Throwable {
				System.out.println("前置通知...before");
			}
		};
		
		//返回后通知
		Advice afterReturning=new AfterReturningAdvice() {
			
			@Override
			public void afterReturning(Object arg0, Method arg1, Object[] arg2,
					Object arg3) throws Throwable {
				System.out.println("返回后通知...afterReturning");
			}
		};
		
		Advice around=new MethodInterceptor() {
			
			@Override
			public Object invoke(MethodInvocation arg0) throws Throwable {
				System.out.println("在前面拦");
				Object returnValue=arg0.proceed();
				System.out.println("在后面拦");
				return returnValue;
			}
		};
		
		//切面 = 切点 + 通知
		Advisor advisor1=new DefaultPointcutAdvisor(before);
		Advisor advisor2=new DefaultPointcutAdvisor(afterReturning);
		Advisor advisor3=new DefaultPointcutAdvisor(around);
		
		factory.addAdvisors(advisor3,advisor2,advisor1);//2 给代理工厂一个切面 ---注意,添加的顺序的拦截动作执行的顺序是有关系的!!!
		//其实也就只有一种情况要注意,就是环绕的around这种放在最前面添加这种,会把其他的通知都包括进去,
		//即,环绕的这种的前面拦截的会在最前面,后面拦截的会在最后面
		Person p2=(Person) factory.getObject();//3 从代理工厂中获取一个代理后的对象
		p2.run();
		p2.speak();
	}
}


例二(此例要更加深入一些):
Person.java

 

 

package cn.hncu.spring4.aop.demo4;

public class Person {
	public void run(){
		System.out.println("I'm running...");
	}
	public void run(int i){
		System.out.println("I'm running..."+i);
	}
	public void speak(){
		System.out.println("I'm speaking...");
	}
}

AopXmlDemo.java  此类中用到了四个配置文件,在下面我都会贴出来,每一个都不一样

 

 

package cn.hncu.spring4.aop.demo4;

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

public class AopXmlDemo {
	@Test//采用配置文件的方式使用切面拦截
	public void demo1(){
		ApplicationContext act=new ClassPathXmlApplicationContext("cn/hncu/spring4/aop/demo4/1.xml");
		Person p=act.getBean("personProxied", Person.class);
		p.run();
	}
	
	@Test//把切点和通知配置成 切面的内部bean
	public void demo2(){
		ApplicationContext act=new ClassPathXmlApplicationContext("cn/hncu/spring4/aop/demo4/2.xml");
		Person p=act.getBean("personProxied", Person.class);
		p.run();
	}
	
	@Test//直接在切面bean中配置“切点的正则表达式”,省去“切点bean”的配置
	public void demo3(){
		ApplicationContext act=new ClassPathXmlApplicationContext("cn/hncu/spring4/aop/demo4/3.xml");
		Person p=act.getBean("personProxied", Person.class);
		p.run();
	}
	
	@Test
	public void demo4(){
		ApplicationContext act=new ClassPathXmlApplicationContext("cn/hncu/spring4/aop/demo4/4.xml");
		Person p=act.getBean(Person.class);
		p.run();
	}
}

AroundAdvice.java

 

 

package cn.hncu.spring4.aop.demo4;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class AroundAdvice implements MethodInterceptor {

	@Override
	public Object invoke(MethodInvocation methodInv) throws Throwable {
		System.out.println("前面拦");
		Object resObj=methodInv.proceed();
		System.out.println("后面拦");
		return resObj;
	}

}

配置文件

 

1.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:tx="http://www.springframework.org/schema/tx"
		xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
				http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
				http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

	<bean id="p" class="cn.hncu.spring4.aop.demo4.Person"></bean>
	
	<!-- 切点 -->
	<bean id="cut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
		<property name="pattern" value=".*run.*"></property>
	</bean>
	<!-- 通知 -->
	<bean id="advice" class="cn.hncu.spring4.aop.demo4.AroundAdvice"></bean>
	<!-- 切面=切点+通知 -->
	<bean id="advisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
		<property name="pointcut" ref="cut"></property>
		<property name="advice" ref="advice"></property>
	</bean>
	
	<bean id="personProxied" class="org.springframework.aop.framework.ProxyFactoryBean">
		<property name="target" ref="p"></property>
		<property name="interceptorNames">
			<list>
				<value>advisor</value>
			</list>
		</property>
	</bean>
</beans>

2.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:tx="http://www.springframework.org/schema/tx"
		xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
				http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
				http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

	<bean id="p" class="cn.hncu.spring4.aop.demo4.Person"></bean>
	
	<!-- 切面=切点+通知 (把切点和通知写成内部bean)-->
	<bean id="advisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
		<property name="pointcut">
			<bean id="cut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
				<property name="pattern" value=".*run.*"></property>
			</bean>
		</property>
		<property name="advice">
			<bean id="advice" class="cn.hncu.spring4.aop.demo4.AroundAdvice"></bean>
		</property>
	</bean>
	
	<bean id="personProxied" class="org.springframework.aop.framework.ProxyFactoryBean">
		<property name="target" ref="p"></property>
		<property name="interceptorNames">
			<list>
				<value>advisor</value>
			</list>
		</property>
	</bean>
</beans>

3.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:tx="http://www.springframework.org/schema/tx"
		xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
				http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
				http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

	<bean id="p" class="cn.hncu.spring4.aop.demo4.Person"></bean>
	
	<!-- 切面=切点+通知 (把切点和通知写成内部bean),直接在切面bean中配置“切点的正则表达式”,省去“切点bean”的配置-->
	<bean id="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
		<property name="patterns">
			<list>
				<value>.*run.*</value>
			</list>
		</property>
		
		<property name="advice">
			<bean id="advice" class="cn.hncu.spring4.aop.demo4.AroundAdvice"></bean>
		</property>
	</bean>
	
	<bean id="personProxied" class="org.springframework.aop.framework.ProxyFactoryBean">
		<property name="target" ref="p"></property>
		<property name="interceptorNames">
			<list>
				<value>advisor</value>
			</list>
		</property>
	</bean>
</beans>

4.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:tx="http://www.springframework.org/schema/tx"
		xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
				http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
				http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

	<bean id="p" class="cn.hncu.spring4.aop.demo4.Person"></bean>
	
	<!-- 切面=切点+通知 (把切点和通知写成内部bean),直接在切面bean中配置“切点的正则表达式”,省去“切点bean”的配置-->
	<bean id="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
		<property name="patterns">
			<list>
				<value>.*run.*</value>
			</list>
		</property>
		
		<property name="advice">
			<bean id="advice" class="cn.hncu.spring4.aop.demo4.AroundAdvice"></bean>
		</property>
	</bean>
	
	<!--自动代理 
	  <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
	 -->
	<bean class="cn.hncu.spring4.aop.demo4.MyAutoProxy"></bean>
</beans>

MyAotuProxy.java 这是自己写的一个自动代理(在用ApplicationContext新建对象的时候自动为它代理),这个是配合4.xml用的,因此就和4.xml放一起了



 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值