AOP

1 Improve the Account case

ThreadLocal objects bind Connnection to the current thread so that only one object in a thread can control a transaction.

The server thread pool Tomcat is created

2 Analyzing problems

Review technical dynamic proxies

Dynamic proxy:

Dynamic proxy based on interface

Public void saleProduct(float money); /** * public void saleProduct(float money); /** * @param */ public void afterProduct(float money); } public class implements ProduceInterdace {/** * @param */ public void saleProduct(float money) { System.out.println(" sell money" + money); } public void afterProduct(float money) {system.out.println (" float money "+money); } } public static void main(final String[] args) { final Produce produce = new Produce(); produce.saleProduct(1000); ProduceInterdace produceInterdace = (ProduceInterdace)Proxy.newProxyInstance(produce.getClass().getClassLoader(), produce.getClass().getInterfaces(), New InvocationHandler() {/** * any interface method that executes the promenade object passes through this method * @param o reference to the promenade object * @param method The currently executed method * @param Objects @throw Throwable */ Public Object invoke(Object O, Method Method, Object[] objects) throws Throwable {// Enhanced code Object returnValue = null; Float money = (Float)objects[0]; Float money = (Float)objects[0]; If ("saleProduct".equals(method.getName())) {returnValue = method.invoke(produce, money*0.8f); } return returnValue; }}); produceInterdace.saleProduct(1000f); }Copy the code

Subclass-based dynamic proxy

increase

<dependencies> <dependency> <groupId>cglib</groupId> <artifactId> <version>2.1_3</version> </dependency> </dependencies> public static void main(final String[] args) { final Produce produce = new Produce(); produce.saleProduct(1000); /** * dynamic proxy * bytecode load as you go load as you go method enhancement without modifying source code * classification: * interface based dynamic proxy * subclass based dynamic proxy * subclass based dynamic proxy: Enhancer Classes * Provider cglib * How to create a proxy object: * Using the create method in the Enhancer class * To create a proxy object requirements: * The promenade class cannot be the final class * Create method parameters: * Class bytecode * specifies the bytecode of the propped object * Callback is used to provide enhanced code * how to proide. Generally, this interface implements the class. MethodInterceptor */ Produce Produce1 = (Produce)Enhancer.create(produce.getClass(), New MethodInterceptor() {/** * any method that executes the propeted object passes through this method * @param o * @param method * @param objects * @param methodProxy The proxy Object of the currently executing method @return * @throws Throwable */ Public Object intercept(Object o, Method method, Object[] objects, MethodProxy MethodProxy) throws Throwable {// Enhanced code Object returnValue = null; Float money = (Float)objects[0]; Float money = (Float)objects[0]; If ("saleProduct".equals(method.getName())) {returnValue = method.invoke(produce, money*0.8f); } return returnValue; }}); produce1.saleProduct(20000); }Copy the code

A dynamic proxy

4. Another way to implement dynamic proxy 5. Solve case problems

AOP concepts

Section-oriented programming

The repetitive code of the program is extracted, and when it needs to be executed, the dynamic proxy technology is used to enhance our existing methods without modifying the source code.

The role and advantages of AOP

What it does: Enhances existing methods without modifying the source code while the program is running.

Advantage:

Reduce duplicate code

Improve development efficiency

Maintenance is convenient

Implementation of AOP

Use dynamic proxy techniques

Aop related terms in Spring

AOP related terms

Joinpoint: (Business layer method) Join points are those points that are intercepted. In Spring, these points refer to methods, because Spring only supports join points of method types.

Pointcuts: All pointcuts are join points. Pointcuts are the definition of which JoinPoints we want to intercept.

Advice: Advice means that all you need to do after intercepting Joinpoint is advise.

Type of notice:

Invoke method.invoke(produce, money*0.8f) before executing

Invoke (produce, money*0.8f) after postnotification method.invoke

Exception notification catch execution

Finally notify FINNAL to execute

Surround notification. The entire Invoke method executes. There are explicit pointcut method calls.

The Introduction (Introduction) :

Introduction is a special kind of notification. Without modifying the class code, Introduction can dynamically add methods or fields to a class at run time.

Target:

The target object of the proxy. (Proxied object)

Has (weave) :

The process of applying an enhancement to a target object to create a new proxy object. Spring uses dynamic proxy weaving, while AspectJ uses compile-time weaving and class-load weaving.

Proxy: (Proxy object)

When a class is woven into AOP for enhancement, a result proxy class is produced.

Aspect (section) :

It is a combination of pointcuts (enhancements) and notifications (introductions).

Class methods method execution and so on.

XML – and annotation-based configuration in Spring

notice

<! AOP--> < AOP :config> <! Configure the pointcut expression ID attribute to specify the unique identity of the expression. The expression attribute is used to specify the expression content. This tag is written inside the AOP :aspect tag and can only be used on the current aspect. It can also be written in the book of aop: outside the aspect, becomes all aspects can be used at this time - > < aop: pointcut id = "pt1 expression" = "execution (* com. Itheima. Service. Impl. *. * (..) )"></aop:pointcut> <! Aop :aspect id="logAdvice" ref="logger"> <! < AOP :before method="beforePrintLog" pointcut-ref=" pT1 "></ AOP :before>--> <! Configure post-notification: value after the pointcut method executes normally. It and exception notification can always only execute one < AOP :after-returning method="afterReturningPrintLog" pointcut-ref=" pT1 "></ AOP :after-returning>--> <! Configure exception notification: executed after the pointcut method execution produces an exception. It and post-notification can only ever execute one < AOP :after-throwing method="afterThrowingPrintLog" pointcut-ref=" pT1 "></ AOP :after-throwing>--> <! < AOP :after method="afterPrintLog" pointcut-ref="pt1"></ AOP :after>--> <! < AOP :around method=" arounddpringlog "pointcut-ref=" pT1 "></ AOP :around> </aop:aspect> </aop:config> /** * Wrap advice * Problem: * When we configure wrap advice, the pointcut method does not execute, but the advice method does. * Analysis: * By comparing the surround notification code in the dynamic proxy, we found that the dynamic proxy's surround notification has an explicit pointcut method call, which our code does not. The Spring framework provides an interface: ProceedingJoinPoint. The interface has a method proceed(), which is equivalent to explicitly calling the pointcut method. * This interface can be used as a method parameter around the notification, and the Spring framework will provide us with an implementation class for this interface to use when the program executes. * * Wrap notification in Spring: * It is a way that the Spring framework gives us to manually control in our code when enhancements are executed. */ public Object aroundPringLog(ProceedingJoinPoint pjp){ Object rtValue = null; try{ Object[] args = pjp.getArgs(); System.out.println(" The around-DPRingLog method in the Logger class starts logging... Front "); rtValue = pjp.proceed(args); // Explicitly call the business layer method (pointcut method) System.out.println(" The around-DPRingLog method in the Logger class starts logging... Rear "); return rtValue; }catch (Throwable t){system.out.println (" The around-DPRingLog method in the Logger class starts logging... Abnormal "); throw new RuntimeException(t); }finally {system.out. println(" The around-DPRingLog method in the Logger class starts logging... In the end "); }}Copy the code

Pointcut expression specification

Execution: The execution(often) of a matching method.

The package name of the return value type. Class name. Method name (parameter)

Full matching mode:

public void com.itheima.service.impl.AccountServiceImpl.saveAccount(com.itheima.domain.Account)

Access modifiers can be omitted

void com.itheima.service.impl.AccountServiceImpl.saveAccount(com.itheima.domain.Account)

The return value can be an asterisk (*) to indicate any return value

  • com.itheima.service.impl.AccountServiceImpl.saveAccount(com.itheima.domain.Account)

The package name can use a number to indicate any package, but there are several levels of packages, and several need to be written

  • ....AccountServiceImpl.saveAccount(com.itheima.domain.Account)

Use.. To represent the current package and its subpackages

  • com.. AccountServiceImpl.saveAccount(com.itheima.domain.Account)

The class name can be an asterisk (*) to indicate any class

  • com.. *.saveAccount(com.itheima.domain.Account)

Method names can be marked with an asterisk (*) to indicate any method

  • com...( com.itheima.domain.Account)

Parameter lists can use * to indicate that the parameter can be of any data type, but must have parameters

  • com...(*)

Parameter lists can use.. Indicates that the parameter can be of any type

  • com...(..)

Full wildcard mode: *… * (..)

Note: Typically, we are enhancing the business layer methods, so pointcut expressions are cut to the business layer implementation class. execution(* com.itheima.service.impl.. (..) )

AOP annotations

@aspect // Indicates that the current class is an Aspect class

@Before

Action: Treats the current method as a pre-notification. Property: value: Used to specify a pointcut expression, and can also specify a reference to a pointcut expression.

@Before(“execution(* com.itheima.service.impl.. (..) )”

@AfterReturning

Action: Treats the current method as a post-notification. Property: value: Used to specify a pointcut expression, and can also specify a reference to a pointcut expression

@AfterReturning(“execution(* com.itheima.service.impl.. (..) )”

@AfterThrowing

Action: Treats the current method as an exception notification. Property: value: Used to specify a pointcut expression, and can also specify a reference to a pointcut expression

@AfterThrowing(“execution(* com.itheima.service.impl.. (..) )”

@AfterThrowing

Action: Treats the current method as an exception notification. Property: value: Used to specify a pointcut expression, and can also specify a reference to a pointcut expression

@After

Action: Treats the current method as the final notification. Property: value: Used to specify a pointcut expression, and can also specify a reference to a pointcut expression

Surrounding the notification

@Around

Action: Think of the current method as a wrap notification. Property: value: Used to specify a pointcut expression, and can also specify a reference to a pointcut expression.

Pointcut expression annotations

@Pointcut

Value: Specifies the content of the expression

@Pointcut(“execution(* com.itheima.service.impl.. (..) )”) private void pt1() {}

@param PJP @return */ @around (“pt1()”) Public Object transactionAround(ProceedingJoinPoint PJP) {return rtValue = null; Object[] args = pjp.getargs (); BeginTransaction (); Proceed (args); // Proceed (rtValue = pjP.proceed); Commit transaction commit(); }catch(Throwable e) {rollback(); e.printStackTrace(); }finally {// Finally: release resource release(); } return rtValue; }

Use XML configuration

<! <context:component-scan base-package="com.itheima"></context:component-scan> <! < AOP :aspectj-autoproxy></ AOP :aspectj-autoproxy>Copy the code

Configuration without XML

@Configuration 
@ComponentScan(basePackages="com.itheima") @EnableAspectJAutoProxy 
public class SpringConfiguration { } 
Copy the code