Spring1.4——AOP和AOP的事务处理的实现

Javaweb框架学习文章索引点这里
AOP介绍:

  • 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
  • AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码
  • 主要应用于日志记录,性能统计,安全控制,事务处理,异常处理等
  • Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码
  • AspectJ是一个基于Java语言的AOP框架,Spring2.0开始,Spring AOP引入对Aspect的支持,AspectJ扩展了Java语言,提供了一个专门的编译器,在编译时提供横向代码的织入

AOP在Spring中的实现:
- 在Spring中aop底层使用代理机制进行实现
- 如果有接口是和实现类则使用jdk中的动态代理方式即Proxy
- 如果没有接口,只有实现类则采用cglib字节码增强方式

Spring中AOP术语:

  • Target:目标类,需要被代理的类
  • Joinpoin:连接点,指可能被拦截到的方法
  • PointCut:切入点,已经被增强的连接点
  • Advice: 通知,即是给目标类进行增强的代码
  • Weaving:织入,指把Advice应用到Target来创建Proxy对象的过程
  • Proxy:代理类,一般是Spring自动生成
  • Aspect:切面,Pointcut和Advice的结合

以下例子主要是事务实现

手动使用动态代理:
切入点类:

public interface BookService {
    public void addBook();
    public void deleteBook();
    public void selectBook();
}
public class BookServiceImpl implements BookService{

    @Override
    public void addBook() {
        System.out.println("add books");
    }

    @Override
    public void deleteBook() {
        System.out.println("delete books");
    }

    @Override
    public void selectBook() {
        System.out.println("select books");
    }
}

通知类:

public class MyAspect {
    public void before(String methodName) {
        System.out.println("before:"+methodName);
    }

    public void after(String methodName) {
        System.out.println("after:"+methodName);
    }
}

动态代理及测试类:

package com.g_a_aop_jdk;

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

import org.junit.Test;

public class MyFactory {
    public BookService createBookService() {
        BookService bookService = new BookServiceImpl();
        MyAspect aspect = new MyAspect();

        BookService proxyService = (BookService)Proxy.newProxyInstance(
                MyFactory.class.getClassLoader(),
                bookService.getClass().getInterfaces(),
                new InvocationHandler() {
                //动态代理其实就是基于接口生成的代理类,每个代理类中的方法都调用invoke方法来增强原来的方法
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //执行事务逻辑
                        aspect.before(method.getName());
                        Object object = method.invoke(bookService, args);//调用原来的方法
                        aspect.after(method.getName());
                        return object;
                    }
                });

        return proxyService;
    }
    @Test
    public void test1() {
        BookService bookService = createBookService();
        bookService.addBook();
        bookService.deleteBook();
        bookService.selectBook();
    }
}

结果:

before:addBook
add books
after:addBook
before:deleteBook
delete books
after:deleteBook
before:selectBook
select books
after:selectBook

手动使用cglib:
切入点类:

public class BookServiceImpl{

    public void addBook() {
        System.out.println("add books");
    }
    public void deleteBook() {
        System.out.println("delete books");
    }
    public void selectBook() {
        System.out.println("select books");
    }
}

通知类:

public class MyAspect {
    public void before(String methodName) {
        System.out.println("before:"+methodName);
    }

    public void after(String methodName) {
        System.out.println("after:"+methodName);
    }
}

cglib和测试类

public class MyFactory {
    public BookServiceImpl createBookService() {
        BookServiceImpl bookService = new BookServiceImpl();
        MyAspect aspect = new MyAspect();
        /*cglib是对于目标类生成它的子类对象作为代理类*/
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(bookService.getClass());//确定父类,这里即是目标类
        enhancer.setCallback(new MethodInterceptor() {//设置回调函数
            @Override
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                //执行原来的方法和进行增强
                aspect.before(method.getName());

                //Object object = method.invoke(bookService, args);

                //效果同上,proxy表示的代理对象的父类对象,即是目标对象
                Object object = methodProxy.invokeSuper(proxy, args);//执行原来的方法
                aspect.after(method.getName());
                return object;
            }
        });
        BookServiceImpl proxyService = (BookServiceImpl)enhancer.create();
        return proxyService;
    }
    @Test
    public void test1() {
        BookServiceImpl bookService = createBookService();
        bookService.addBook();
        bookService.deleteBook();
        bookService.selectBook();
    }
}

结果同上

使用Spring内置的动态代理工厂(半自动):
切入点类:

public interface BookService {
    public void addBook();
    public void deleteBook();
    public void selectBook();
}
package com.g_b_Factorybean;

public class BookServiceImpl implements BookService{
    public void addBook() {
        System.out.println("add books");
    }
    public void deleteBook() {
        System.out.println("delete books");
    }
    public void selectBook() {
        System.out.println("select books");
    }
}

通知类:

package com.g_b_Factorybean;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
//采用“环绕通知” MethodInterceptor
public class MyAspect implements MethodInterceptor{

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {

        System.out.println("before1");
        //环绕通知要手动执行目标方法
        Object object = mi.proceed();
        System.out.println("after1");
        return object;
    }
}

配置文件:

<?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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--配置切入点类-->
    <bean name="BookService" class="com.g_b_Factorybean.BookServiceImpl"></bean>
    <!--配置通知类-->
    <bean name="MyAspect" class="com.g_b_Factorybean.MyAspect"></bean>
    <!--配置Spring内置的动态代理工厂类
        interfaces是接口名,如果有多个则使用<array>节点进行配置单个则使用value
        target是目标类,这里直接指向目标类
        interceptorNames是配置通知类,多个用<array>配置,单个用value
    -->
    <bean name="ProxyService" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="interfaces" value="com.g_b_Factorybean.BookService"></property>
        <property name="target" ref="BookService"></property>
        <property name="interceptorNames" value="MyAspect"></property>
    </bean>
</beans>

测试类:

    @Test
    public void test1() {
        String xmlPath = "com/g_b_Factorybean/beans.xml";
        ApplicationContext appcont = new ClassPathXmlApplicationContext(xmlPath);

        BookService bookService = (BookService) appcont.getBean("ProxyService");
        bookService.addBook();
        bookService.selectBook();
        bookService.deleteBook();
    }

结果:

before1
add books
after1
before1
select books
after1
before1
delete books
after1

使用Spring AOP编程(全自动):
切入点类:

package com.g_c_aopbyspring;

public interface BookService {
    public void addBook();
    public void deleteBook();
    public void selectBook();
}
package com.g_c_aopbyspring;

public class BookServiceImpl implements BookService{
    public void addBook() {
        System.out.println("add books");
    }
    public void deleteBook() {
        System.out.println("delete books");
    }
    public void selectBook() {
        System.out.println("select books");
    }
}

通知类:

package com.g_c_aopbyspring;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
//采用“环绕通知” MethodInterceptor
public class MyAspect implements MethodInterceptor{

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {

        System.out.println("before2");
        //手动执行目标方法
        Object object = mi.proceed();
        System.out.println("after2");
        return object;
    }
}

配置文件:

<?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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/aop
                           http://www.springframework.org/schema/aop/spring-aop.xsd
                           ">

    <bean name="BookService" class="com.g_c_aopbyspring.BookServiceImpl"></bean>
    <bean name="MyAspect" class="com.g_c_aopbyspring.MyAspect"></bean>
    <!--使用AspectcJ配置com.g_c_aopbyspring包下任意类和方法(任意参数)都是连接点,它们的id为myPointCut
        然后配置一个通知类引用MyAspect,对应的切入点的引用是myPointCut
    -->
    <aop:config>
        <aop:pointcut expression="execution(* com.g_c_aopbyspring.*.*(..))" id="myPointCut"/>
        <aop:advisor advice-ref="MyAspect" pointcut-ref="myPointCut"/>
    </aop:config>
</beans>

测试类:

    @Test
    public void test1() {
        String xmlPath = "com/g_c_aopbyspring/beans.xml";
        ApplicationContext appcont = new ClassPathXmlApplicationContext(xmlPath);
        //就是直接使用原来的id名,但是获取到的已经是装饰过的对象
        BookService bookService = (BookService) appcont.getBean("BookService");
        bookService.addBook();
        bookService.selectBook();
        bookService.deleteBook();
    }

结果:

add books
after2
before2
select books
after2
before2
delete books
after2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值