Spring - Configuration in Spring1 of AOP(1)

Introduction to AOP

AOP (Aspect-Oriented Programming), that is, aspect-oriented programming, as a supplement to object-oriented (OOP, Object-Oriented Programming), is widely used to deal with some system-level services with cross-cutting properties, such as security checking and logging. , business management, etc.

In OOP, we take classes as the basic unit, and the basic unit in AOP is Aspect .

Defining AOP Terms

  • 1. Aspect

The cross-functionality to be achieved is an aspect or field of system modularity. such as logging.

AspectConsists of pointcutand advice, which contains both the definition of crosscutting logic and the definition of join points. Spring AOP is the framework responsible for implementing aspects, weaving the cross-cutting logic defined by the aspect into the join points specified by the aspect.

  • 2. Join Point

The place where the aspect is inserted during the execution of the application, which can be a method call, an exception thrown, or a field to be modified.

In Spring AOP, there Join Pointis always the execution point of the method, i.e. only the method join point.

  • 3. Advice

The actual implementation of the aspect, which informs the system of new behavior. For example, the log notification contains code that implements logging functions, such as writing logs to the log file. Notifications are inserted into the application system at the connection point.

Many AOP frameworks, including Spring AOP, will Advicesimulate an interceptor (Interceptor), and Join Pointmaintain multiple on Adviceit to intercept layer by layer.

  • 4. Point Cut

Defines which join points the notification should be applied to. The notification can be applied to any join point supported by the AOP framework. Adviceis Point Cutassociated with a specific one, and executes in Point Cuta matching one Join Point.

In Spring, all methods can be considered as yes Join Point, but we do not want to add them to all methods Advice, but Point Cutthe role is to provide a set of rules (which can Aspect pointcut expression languagebe described by using) to match and add Join Pointto meet the rules .Join PointAdvice

  • 5. Introduction

Add new methods and properties to the class. Adviced ObjectSpring AOP allows us to introduce new interfaces (and corresponding implementations) to the target object .

  • 6. Advised Object

The object to be notified. It can be a class you wrote or a third-party class.

  • 7. Proxy object (AOP Proxy)

Object created after applying notification( Advice) to the target object, no other parts of the application system need to be changed to support the proxy object.

Spring AOP uses runtime proxies to implement aspects. In Spring AOP, an AOP proxy is a JDK dynamic proxy object or a CGLIB proxy object.

  • 8. Weaving

The process of applying an aspect to a target object to create a new proxy object. Weaving occurs at multiple points in the target object's lifecycle:

  • Compile-time: Aspects are woven in when the target object is compiled, which requires a special compiler.

  • Class loading time: Aspects are woven when the target object is loaded into the JVM, which requires a special class loader.

  • Runtime: Aspects are woven into the application at runtime.

Spring uses dynamic proxy weaving, and AspectJuses compile-time weaving and class-loading-time weaving.

Create a notification

This article will explain related examples through the configuration method of Spring1, use ProxyFactoryBeanto create AOP proxy, and use the Advisorspecified method to be added.

There are four main types of notifications, as shown in the following table:

Notification type interface describe
Around org.aopalliance.intercept.MethodInterceptor Intercept the call to the target method
Before org.springframework.aop.MethodBeforeAdvice Called before the target method is called
After org.springframework.aop.AfterReturningAdvice Called after the target method is called
Throws org.springframework.aop.ThrowsAdvice Called when the target method throws an exception

Note: Exception notification ThrowsAdviceis an identifying interface without any methods, but classes implementing this interface must have methods of the following form:

void afterThrowing(Throwable throwable);
void afterThrowing(Method m, Object[] objects, Object target, Exception throwable);

The first method accepts only one parameter: the exception that needs to be thrown.

The second method accepts the exception, the method called, parameters, and the target object.

Introduce notice

Introducing notifications can customize the pointcut.

Custom pointcuts can be matched by regular expressions.

case

1. Define the interface

two interfaces ITestServiceandITestService2

public interface ITestService {
    void sayHello();
}

public interface ITestService2 {
    void sayBye();
}

2. Write the object (the proxied object, that is, the target object)

The target object has nameproperties, and it has sayHello()methods and sayBye()methods.

public class TestService1 implements ITestService, ITestService2 {
    private String name;

    public String getName() {
        return name;
    }

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

    @Override
    public void sayHello() {
        System.out.println("Hello, " + name);
    }

    @Override
    public void sayBye() {
        System.out.println("Bye, " + name);
        try {
            int i = 1 / 0;
        } catch (Exception e) {
        }
    }
}

3. Write a notification

Here we write the 4 notifications introduced above.

public class MyMethodBeforeAdvice implements MethodBeforeAdvice {
    /**
     *
     * @param method 被调用的方法
     * @param objects 给方法传递的参数
     * @param o 被代理的对象,目标对象
     * @throws Throwable
     */
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("=============");
        System.out.println("记录日志:" + method.getName());
    }
}

public class MyAfterReturningAdvice implements AfterReturningAdvice {

    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("关闭资源....");
    }
}

public class myMethodInterceptor implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        System.out.println("调用方法前执行!");
        // proceed()真正执行方法,object为返回的对象
        Object object = methodInvocation.proceed();
        System.out.println("方法调用后!");
        return object;
    }
}

public class MyThrowsAdvice implements ThrowsAdvice {

    public void afterThrowing(Method m, Object[] objects, Object target, Exception throwable){
        System.out.println("出大事了!" + throwable.getMessage());
    }
}

4. Configure in the beans.xml file

4.1 First configure the proxy object

4.2 Configuring Notifications

4.3 Configure the proxy object, yes ProxyFactoryBeaninstance

4.3.1 Configuring the Agent Interface Set

4.3.2 Weaving notifications into proxy objects

4.3.3 Specifying the Proxy Object

  • The configuration file is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">
    <!--配置被代理的对象-->
    <bean id="testService1" class="com.gavin.aop.TestService1">
        <property name="name" value="Gavin"/>
    </bean>

    <!--配置前置通知-->
    <bean id="myMethodBeforeAdvice" class="com.gavin.aop.MyMethodBeforeAdvice"/>
    <!--配置后置通知-->
    <bean id="myAfterReturningAdvice" class="com.gavin.aop.MyAfterReturningAdvice"/>
    <!--配置环绕通知-->
    <bean id="myMethodInterceptor" class="com.gavin.aop.myMethodInterceptor"/>
    <!--配置异常通知-->
    <bean id="myThrowsAdvice" class="com.gavin.aop.MyThrowsAdvice"/>

    <!--使用Advisor来定义前置通知的切入点,该定义只允许sayHello使用前置通知,sayBye不使用前置通知-->
    <bean id="myMethodBeforeAdviceFilter" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
        <property name="advice" ref="myMethodBeforeAdvice"/>
        <property name="mappedNames">
            <list>
                <value>sayHello</value>
            </list>
        </property>
    </bean>

    <!--配置代理对象-->
    <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!--代理接口集-->
        <property name="proxyInterfaces">
            <list>
                <value>com.gavin.aop.ITestService</value>
                <value>com.gavin.aop.ITestService2</value>
            </list>
        </property>
        <!--把通知织入到代理对象-->
        <property name="interceptorNames">
            <!--相当于把前置通知和代理对象关联起来-->
            <!--我们也可以把通知看成拦截器-->
            <list>
                <!--使用自定义切入点,来控制前置通知-->
                <value>myMethodBeforeAdviceFilter</value>
                <value>myAfterReturningAdvice</value>
                <value>myMethodInterceptor</value>
                <value>myThrowsAdvice</value>
            </list>
        </property>
        <!--指定被代理对象-->
        <property name="target">
            <ref bean="testService1"/>
        </property>
    </bean>
</beans>

Here, if you only use ProxyFactoryBeanto configure the proxy object, all the methods in the proxy interface will be proxied, that is, each method will be enhanced. If you don't want to be enhanced, we can Advisorspecify the pointcut through configuration. Here we use NameMatchMethodPointcutAdvisor, by specifying the specific method name to specify the method that needs to be enhanced. In addition, if there are many methods, it can also be passed RegexpMethodPointcutAdvisor, and the Advisor can use regular expressions to match the methods to be enhanced.

5. Test class:

public class App1 {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/gavin/aop/beans.xml");
        ITestService iTestService = (ITestService) applicationContext.getBean("proxyFactoryBean");
        iTestService.sayHello();
        System.out.println();
        ((ITestService2)iTestService).sayBye();
    }
}

6. Output

write picture description here

As you can see, TestServicethe sayHello()and sayBye()methods in both are enhanced. Among them, because we have configured the pre-notification and Advisorspecified that only the sayHello()method is woven into the pre-notification, the sayHello()method records the log, but the sayBye()method does not.

In the sayBye()method, since we caught and handled the exception, no exception was reported during the execution of the program, and the exception notification was not called. If in the sayBye()method, we do not handle the exception for int i = 1 / 0;this sentence, the exception will be thrown during execution, and the exception notification will be called.


This article uses the configuration of AOP in Spring1, but there is a problem here. When our business increases, ProxyFactoryBeanthe configuration will also increase, which will xmlquickly become bloated.

The framework will be introduced later AspectJ, as well as the configuration method added in later versions of Spring 2 @AspectJ. What you need to know is that Spring only introduces @AspectJmode configuration, but the way to implement AOP at the bottom is still through proxy, which is different from the AspectJframework.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324509053&siteId=291194637