Spring frame base (04): AOP section programming concepts, several implementations demo

This article Source: GitHub · Click here || GitEE · Click here

A, AOP basis Introduction

1, section Introduction to Programming

Full name AOP: Aspect Oriented Programming, Aspect Oriented Programming. Dynamic proxies to implement a unified technology program functions maintained by way of pre-compiled and run. Central role: can isolate each part of the business logic such that the business logic to reduce the degree of coupling between the parts, to improve development efficiency and reuse program. AOP provides inheritance and replaced by a new commission scheme, and use more simple and clear, is a hot concept in software development.

2, AOP term

(1), the type of notification: Advice

前置通知[Before]:目标方法被调用之前;
返回通知[After-returning]:目标方法执行成功之后;
异常通知[After-throwing]:在目标方法抛出异常之后; 
后置通知[After]:目标方法完成之后;
环绕通知[Around]:在目标方法执行前后环绕通知;

(2), the connection point: JoinPoint

A particular location of the program execution, such as classes before and after the initial running before and after the method.

(3), the tangent point: Pointcut

Connection points are those methods in specified policy might be intercepted.

(4), section: Aspect

Section joined by the tangent point and notifications.

(5), is introduced: Introduction

Special enhancements, add some properties and methods for the class.

(6), weaving: Weaving

Added to the process to enhance the specific connection point of the target class. Compile weaving, which requires the use of special compilers; class loader of weaving, which requires special class loader; dynamic proxy weaving, adding a reinforcing manner subclassing for the target class at runtime, Spring uses dynamic proxy weaving, while the weaving AspectJ using compile and class loading of weaving.

(7), proxy: Proxy

Generating a result class category is woven into the AOP, which is a fusion of the original class and Enhanced Logic proxy class.

Two, AOP program implementation

Stories based on the following classes:

public class Book {
    private String bookName ;
    private String author ;
}
public interface BookService {
    void addBook (Book book) ;
}
public class BookServiceImpl implements BookService {
    @Override
    public void addBook(Book book) {
        System.out.println(book.getBookName());
        System.out.println(book.getAuthor());
    }
}

1, JDK dynamic proxies

public class BookAopProxyFactory {
    public static BookService createService() {
        // 目标类
        final BookService bookService = new BookServiceImpl() ;
        // 切面类
        final BookAspect bookAspect = new BookAspect();
        /*
         * 代理类:将目标类(切入点)和 切面类(通知) 结合
         */
        BookService proxyBookService = (BookService) Proxy.newProxyInstance(
                BookAopProxyFactory.class.getClassLoader(),
                bookService.getClass().getInterfaces(),
                new InvocationHandler() {
                    public Object invoke(Object proxy, Method method,
                                         Object[] args) throws Throwable {
                        // 前执行
                        bookAspect.before();
                        // 执行目标类的方法
                        Object obj = method.invoke(bookService, args);
                        // 后执行
                        bookAspect.after();
                        return obj;
                    }
                });
        return proxyBookService ;
    }
}

2, CgLib bytecode

CGLIB bytecode using a reinforced frame, creating a subclass of the target class at run-time, thereby enhancing the target classes.

public class BookAopCgLibFactory {
    public static BookService createService() {
        // 目标类
        final BookService bookService = new BookServiceImpl() ;
        // 切面类
        final BookAspect bookAspect = new BookAspect();
        // 核心代理类
        Enhancer enhancer = new Enhancer();
        // 确定父类
        enhancer.setSuperclass(bookService.getClass());
        // 设置回调函数
        enhancer.setCallback(new MethodInterceptor() {
            public Object intercept(Object proxy, Method method,
                                    Object[] args,
                                    MethodProxy methodProxy) throws Throwable {
                bookAspect.before();
                Object obj = method.invoke(bookService, args);
                bookAspect.after();
                return obj;
            }
        });
        BookServiceImpl proxyService = (BookServiceImpl) enhancer.create();
        return proxyService ;
    }
}

3, Spring semiautomatic agent

spring to create a proxy object, the proxy object acquired from spring container manually.

  • Profiles
<!-- 创建目标类 -->
<bean id="bookService" class="com.spring.mvc.service.impl.BookServiceImpl" />
<!-- 创建切面类 -->
<bean id="myAspect" class="com.spring.mvc.config.BookAopSpringHalf" />
<!-- 创建代理类 -->
<bean id="proxyFactory" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="interfaces" value="com.spring.mvc.service.BookService" />
    <property name="target" ref="bookService" />
    <property name="interceptorNames" value="myAspect" />
</bean>
  • Class section
public class BookAopSpringHalf implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        System.out.println("Method Before ...");
        Object obj = methodInvocation.proceed();
        System.out.println("Method After ...");
        return obj;
    }
}

4, Spring automatic proxy

Spring containers obtained from the target class, if the configuration Aop, spring will automatically generate proxy.

  • Profiles
<!-- 创建目标类 -->
<bean id="bookService" class="com.spring.mvc.service.impl.BookServiceImpl" />
<!-- 创建切面类 -->
<bean id="myAspect" class="com.spring.mvc.config.BookAopSpringHalf" />
<!-- AOP编程配置 -->
<aop:config proxy-target-class="true">
    <aop:pointcut expression="execution(* com.spring.mvc.service.*.*(..))"
                  id="myPointCut"/>
    <aop:advisor advice-ref="myAspect" pointcut-ref="myPointCut"/>
</aop:config>

5, integrated test

@Test
public void test1 (){
    BookService bookService = BookAopProxyFactory.createService() ;
    Book book = new Book() ;
    book.setBookName("Spring实战");
    book.setAuthor("Craig Walls");
    bookService.addBook(book);
}
@Test
public void test2 (){
    BookService bookService = BookAopCgLibFactory.createService() ;
    Book book = new Book() ;
    book.setBookName("MySQL");
    book.setAuthor("Baron");
    bookService.addBook(book);
}
@Test
public void test3 (){
    String xmlPath = "spring-aop-half.xml";
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(xmlPath);
    BookService bookService = (BookService) context.getBean("proxyFactory");
    Book book = new Book() ;
    book.setBookName("红楼梦");
    book.setAuthor("曹雪芹");
    bookService.addBook(book);
}
@Test
public void test4 (){
    String xmlPath = "spring-aop-all.xml";
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(xmlPath);
    BookService bookService = (BookService) context.getBean("bookService");
    Book book = new Book() ;
    book.setBookName("西游记");
    book.setAuthor("吴承恩");
    bookService.addBook(book);
}

Three, AspectJ programming section

1. Introduction basis

AspectJ AOP framework is a Java-based, after Spring2.0 added support for AspectJ expression pointcuts, by JDK5 annotation technology that allows direct in the class definitions section, the new version of the Spring Framework, recommended way to develop AspectJ AOP program.

2, XML configuration

  • Class section
public class BookAopAspectJ {
    public void myBefore(JoinPoint joinPoint){
        System.out.println("前置通知:" + joinPoint.getSignature().getName());
    }
    public void myAfterReturning(JoinPoint joinPoint,Object ret){
        System.out.println("后置通知:" + joinPoint.getSignature().getName() + " , -->" + ret);
    }
    public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("环绕通知前");
        Object obj = joinPoint.proceed();
        System.out.println("环绕通知前后");
        return obj;
    }
    public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
        System.out.println("抛出异常通知 : " + e.getMessage());
    }
    public void myAfter(JoinPoint joinPoint){
        System.out.println("最终通知");
    }
}
  • Profiles
<!-- 创建目标类 -->
<bean id="bookService" class="com.spring.mvc.service.impl.BookServiceImpl" />
<!-- 创建切面类 -->
<bean id="myAspect" class="com.spring.mvc.config.BookAopAspectJ" />
<!-- 配置AOP编程 -->
<aop:config>
    <aop:aspect ref="myAspect">
        <aop:pointcut expression="execution(* com.spring.mvc.service.impl.BookServiceImpl.*(..))" id="myPointCut"/>
        <!-- 前置通知-->
        <aop:before method="myBefore" pointcut-ref="myPointCut"/>
        <!-- 后置通知 -->
        <aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="ret" />
        <!-- 环绕通知 -->
        <aop:around method="myAround" pointcut-ref="myPointCut"/>
        <!-- 抛出异常 -->
        <aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e"/>
        <!-- 最终通知 -->
        <aop:after method="myAfter" pointcut-ref="myPointCut"/>
    </aop:aspect>
</aop:config>
  • testing method
@Test
public void test1 (){
    String xmlPath = "spring-aop-aspectj-01.xml";
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(xmlPath);
    BookService bookService = (BookService) context.getBean("bookService");
    Book book = new Book() ;
    book.setBookName("三国演义");
    book.setAuthor("罗贯中");
    bookService.addBook(book);
}

3, scanning notes

  • Profiles
<!-- 开启类注解的扫描 -->
<context:component-scan base-package="com.spring.mvc.service.impl" />
<!-- 确定AOP注解生效 -->
<aop:aspectj-autoproxy />
<!-- 声明切面 -->
<bean id="myAspect" class="com.spring.mvc.config.AuthorAopAspectJ" />
<aop:config>
    <aop:aspect ref="myAspect" />
</aop:config>
  • Class Notes section
@Component
@Aspect
public class AuthorAopAspectJ {
    @Pointcut("execution(* com.spring.mvc.service.impl.AuthorServiceImpl.*(..))")
    private void myPointCut(){
    }
    @Before("execution(* com.spring.mvc.service.impl.AuthorServiceImpl.*(..))")
    public void myBefore(JoinPoint joinPoint){
        System.out.println("前置通知:" + joinPoint.getSignature().getName());
    }
    @AfterReturning(value="myPointCut()" ,returning="ret")
    public void myAfterReturning(JoinPoint joinPoint,Object ret){
        System.out.println("后置通知:" +
                joinPoint.getSignature().getName() + " , -->" + ret);
    }
    @Around(value = "myPointCut()")
    public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("环绕通知前");
        Object obj = joinPoint.proceed();
        System.out.println("环绕通知前后");
        return obj;
    }
    @AfterThrowing(
            value="execution(* com.spring.mvc.service.impl.AuthorServiceImpl.*(..))",
            throwing="e")
    public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
        System.out.println("抛出异常通知 : " + e.getMessage());
    }
    @After("myPointCut()")
    public void myAfter(JoinPoint joinPoint){
        System.out.println("最终通知");
    }
}
  • testing method
@Test
public void test2 (){
    String xmlPath = "spring-aop-aspectj-02.xml";
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(xmlPath);
    AuthorService authorService = (AuthorService) context.getBean("authorService");
    System.out.println("作者:"+authorService.getAuthor());
}

Fourth, the source address

GitHub·地址
https://github.com/cicadasmile/spring-mvc-parent
GitEE·地址
https://gitee.com/cicadasmile/spring-mvc-parent

Guess you like

Origin www.cnblogs.com/cicada-smile/p/11750221.html