Spring aop 简单总结

来源:互联网 发布:有人虚拟串口软件 编辑:程序博客网 时间:2024/06/03 12:01

先用jdk,cglib模拟下:

使用JDK动态代理

//当目标类实现了接口,我们可以使用jdkProxy来生成代理对象。

 

package cn.zyj15.aop;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import cn.zyj15.service.impl.PersonServiceBean;/** *  * @author Administrator *实现InvocationHandler接口的即为代理,记实现invoke方法 */public class JDKProxyFactory implements InvocationHandler {    private Object targetObject;public Object createProxyIntance(Object targetObject){this.targetObject = targetObject;//从newProxyInstance方法看出用jdk实现代理必须实现接口/** 第一个参数设置代码使用的类装载器,一般采用跟目标类相同的类装载器* 第二个参数设置代理类实现的接口* 第三个参数设置回调对象,当代理对象的方法被调用时,会委派给该参数指定对象的invoke方法*/return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(), this.targetObject.getClass().getInterfaces(), this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {//环绕通知PersonServiceBean bean = (PersonServiceBean) this.targetObject;Object result = null; if(bean.getUser()!=null){//..... advice()-->前置通知try {result = method.invoke(targetObject, args);//把方法调用委派给目标对象// afteradvice() -->后置通知} catch (RuntimeException e) {//exceptionadvice()--> 例外通知}finally{//finallyadvice(); -->最终通知}}else {System.out.println("没有权限!");}return result;}}

 

 

package junit.test15;import static org.junit.Assert.*;import org.junit.Test;import cn.zyj15.aop.JDKProxyFactory;import cn.zyj15.service.PersonService;import cn.zyj15.service.impl.PersonServiceBean;public class AOPTest {@Testpublic void jdktest() {JDKProxyFactory factory = new JDKProxyFactory();//必须用接口PersonService service = (PersonService) factory.createProxyIntance(new PersonServiceBean(null));service.save("888");}}
 

使用CGLIB生成代理

//CGLIB可以生成目标类的子类,并重写父类非final修饰符的方法。

 

package cn.zyj16.aop;import java.lang.reflect.Method;import cn.zyj16.service.impl.PersonServiceBean;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;public class CGlibProxyFactory implements MethodInterceptor{private Object targetObject;//代理的目标对象public Object createProxyIntance(Object targetObject){this.targetObject = targetObject;Enhancer enhancer = new Enhancer();//该类用于生成代理对象enhancer.setSuperclass(this.targetObject.getClass());//设置代理类的父类。CGLIB可以生成目标类的子类,并重写父类非final修饰符的方法。enhancer.setCallback(this);//设置回调方法return enhancer.create();//创建代理对象}public Object intercept(Object proxy, Method method, Object[] args,MethodProxy  methodProxy) throws Throwable {PersonServiceBean bean = (PersonServiceBean) this.targetObject;Object result = null;if(bean.getUser()!=null){result = methodProxy.invoke(targetObject, args);}return result;}}
 

 

package junit.test16;import static org.junit.Assert.*;import org.junit.Test;import cn.zyj16.service.PersonService;import cn.zyj16.service.impl.PersonServiceBean;import cn.zyj16.aop.CGlibProxyFactory;public class AOPTest {@Test public void cglibTest2(){CGlibProxyFactory factory = new CGlibProxyFactory();//此事创建的代理对象是PersonServiceBean的子类!PersonServiceBean service = (PersonServiceBean) factory.createProxyIntance(new PersonServiceBean("xxx"));service.save("999");}}
 

 

 

AOP中的概念

Aspect(切面):指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样,类是对物体特征的抽象,而切面横切性关注点的抽象.

joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点,实际上joinpoint还可以是field或类构造器)

Pointcut(切入点):所谓切入点是指我们要对那些joinpoint进行拦截的定义.

Advice(通知):所谓通知是指拦截到joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知

Target(目标对象):代理的目标对象

Weave(织入):指将aspects应用到target对象并导致proxy对象创建的过程称为织入.

Introduction(引入):在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.

 

 

使用Spring进行面向切面(AOP)编程

要进行AOP编程,首先我们要在spring的配置文件中引入aop命名空间:

<beans xmlns="http://www.springframework.org/schema/beans"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xmlns:aop="http://www.springframework.org/schema/aop"

       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">

</beans>

 

Spring提供了两种切面声明方式,实际工作中我们可以选用其中一种:

基于XML配置方式声明切面。

基于注解方式声明切面。


基于注解方式声明切面

首先启动对@AspectJ注解的支持(蓝色部分)

 

<?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"      

       xsi:schemaLocation="http://www.springframework.org/schema/beans

           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd

           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

        <aop:aspectj-autoproxy/> 

        <bean id="myInterceptor" class="cn.zyj17.service.MyInterceptor"/>

        <bean id="personService" class="cn.zyj17.service.impl.PersonServiceBean"></bean>

</beans>

 

 

 

 

package cn.zyj17.service;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.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;/** * 切面 * */@Aspectpublic class MyInterceptor {@Pointcut("execution (* cn.zyj17.service.impl.PersonServiceBean.*(..))")private void anyMethod() {}//声明一个切入点@Before("anyMethod() && args(name)")public void doAccessCheck(String name) {System.out.println("前置通知:"+ name);}@AfterReturning(pointcut="anyMethod()",returning="result")public void doAfterReturning(String result) {System.out.println("后置通知:"+ result);}@After("anyMethod()")public void doAfter() {System.out.println("最终通知");}@AfterThrowing(pointcut="anyMethod()",throwing="e")public void doAfterThrowing(Exception e) {System.out.println("例外通知:"+ e);}@Around("anyMethod()")public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {//if(){//判断用户是否在权限System.out.println("进入方法");Object result = pjp.proceed();System.out.println("退出方法");//}return result;}}

 

 

 

package junit.test17;import org.junit.BeforeClass;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import cn.zyj17.service.PersonService;public class SpringAOPTest {@BeforeClasspublic static void setUpBeforeClass() throws Exception {}@Test public void interceptorTest(){ApplicationContext cxt = new ClassPathXmlApplicationContext("beans.xml");PersonService personService = (PersonService)cxt.getBean("personService");//接口personService.save("xx");}}
 

 

基于基于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"             xsi:schemaLocation="http://www.springframework.org/schema/beans           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">       <aop:aspectj-autoproxy/>         <bean id="personService" class="cn.zyj19.service.impl.PersonServiceBean"></bean>        <bean id="aspetbean" class="cn.zyj19.service.MyInterceptor"/>        <aop:config>        <aop:aspect id="asp" ref="aspetbean">        <aop:pointcut id="mycut" expression=" execution(* cn.zyj19.service..*.*(..))"/>        <aop:before pointcut-ref="mycut" method="doAccessCheck"/>        <aop:after-returning pointcut-ref="mycut" method="doAfterReturning"/>  <aop:after-throwing pointcut-ref="mycut" method="doAfterThrowing"/>  <aop:after pointcut-ref="mycut" method="doAfter"/>  <aop:around pointcut-ref="mycut" method="doBasicProfiling"/>        </aop:aspect>        </aop:config></beans>

 package cn.zyj19.service;

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.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;/** * 切面 * */public class MyInterceptor {public void doAccessCheck() {System.out.println("前置通知");}public void doAfterReturning() {System.out.println("后置通知");}public void doAfter() {System.out.println("最终通知");}public void doAfterThrowing() {System.out.println("例外通知");}public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {System.out.println("进入方法");Object result = pjp.proceed();System.out.println("退出方法");return result;}}
 

 

package junit.test19;import org.junit.BeforeClass;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import cn.zyj19.service.PersonService;public class SpringAOPTest {@BeforeClasspublic static void setUpBeforeClass() throws Exception {}@Test public void interceptorTest(){ApplicationContext cxt = new ClassPathXmlApplicationContext("beans.xml");PersonService personService = (PersonService)cxt.getBean("personService");personService.save("xx");}}
 

 

 

 

 

 

 

 

 

 

 

  • itcastSpring.rar (7 MB)
  • 下载次数: 26
原创粉丝点击