Spring Day 3
- Introduction to AOP
- What is AOP?
- The Role and Advantage of AOP
- Terminology related to AOP
- Joinpoint
- Pointcut (entry point)
- Advice (Notification/Enhancement)
- Introduction (Introduction)
- Target (Target Object)
- Weaving
- Proxy (proxy)
- Aspect
- What you need to be clear about learning AOP in spring
- XML-based AOP configuration (improves transaction control transfer cases above)
- Annotation-based AOP configuration (improves transaction control transfer cases above)
Introduction to AOP
What is AOP?
AOP (full name: Aspect Oriented Programming) is Face-Oriented Programming. It is the continuation of OOP, which is also called Spring as the two core of IOC.In Spring, it is mainly used to isolate parts of business logic, which reduces the coupling between parts of business logic, improves the reusability of programs, and greatly improves the efficiency of development.
The Role and Advantage of AOP
Effect
Enhance existing methods, that is, use dynamic proxies, without modifying the source code while the program is running.
advantage
- Reduce duplicate code
- Improving development efficiency
- Easy maintenance
Introducing learning cases - adding transaction support to the business tier
Business tier code
package com.gzgs.service.impl; import com.gzgs.dao.AccountDao; import com.gzgs.domain.Account; import com.gzgs.service.AccountService; import java.util.List; public class AccountServiceImpl implements AccountService { private AccountDao accountDao; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } public List<Account> findAll() { return accountDao.findAll(); } public Account findAccountById(int id) { return accountDao.findAccountById(id); } public void insertAccount(Account account) { accountDao.insertAccount(account); } public void deleteAccount(int id) { accountDao.deleteAccount(id); } public void updateAccount(int id, Account account) { accountDao.updateAccount(id,account); } public void transfer(String sourceName, String targetName, double money) { //Query outgoing accounts Account source = accountDao.findAccountByName(sourceName); //Query Transfer Account Account target=accountDao.findAccountByName(targetName); //Transfer account deduction source.setMoney(source.getMoney()-money); //Transfer to account to add money target.setMoney(target.getMoney()+money); //Update outgoing accounts accountDao.updateAccount(source.getId(),source); //Update Transferred Account accountDao.updateAccount(target.getId(),target); } }
Proxy Object Factory Code
package com.gzgs.factory; import com.gzgs.service.AccountService; import com.gzgs.utils.TransactionManager; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * A proxy object factory for creating a Service */ public class BeanFactory { private AccountService accountService; private TransactionManager txManager; public void setAccountService(AccountService accountService) { this.accountService = accountService; } public void setTxManager(TransactionManager txManager) { this.txManager = txManager; } public AccountService getAccountService(){ return (AccountService) Proxy.newProxyInstance(accountService.getClass().getClassLoader(), accountService.getClass().getInterfaces(), new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object rtValue=null; try { //Open Transaction txManager.beginTransaction(); //Perform operation rtValue = method.invoke(accountService, args); //Submit Transaction txManager.commit(); //Return results return rtValue; }catch (Exception e){ txManager.rollback(); throw new RuntimeException(e); }finally { //Release Connection txManager.release(); } } }); } }
Terminology related to AOP
Joinpoint
Connection points are those that are intercepted.In spring, these points refer to methods, because spring only supports method types
Connection points, for example, are all methods in AccountServiceImpl.
Pointcut (entry point)
The starting point is the definition of which Joinpoint s we want to intercept, which is the way we need to enhance them.Conceptually, all entry points are connection points, and connection points are not necessarily entry points.
Advice (Notification/Enhancement)
Notification means that what you do after intercepting a Joinpoint is notification.
The types of notifications: pre-notification, post-notification, exception notification, final notification, surround notification, depending on the location relative to the entry point.
Introduction (Introduction)
Introduction s are special notifications that dynamically add parties to a class at run time without modifying its class code
Method or Field.
Target (Target Object)
The target object of the proxy, AccountServiceImpl in the example above.
Weaving
This refers to the process of applying enhancements to the target object to create a new proxy object.
spring uses dynamic proxy weaving, while AspectJ uses compile-time weaving and class-loading weaving.
Proxy (proxy)
When a class is enhanced by AOP weaving, a result proxy class is produced, which is the return result of getAccountService in the example above.
Aspect
Is the combination of entry point and notification (introductory)
What you need to be clear about learning AOP in spring
Development phase (what we do)
Write core business code (main line of development): Most programmers do this, requiring familiarity with business needs.
Pull out the common code and make a notification.(Do it last in the development phase): AOP programmers do it.
In the configuration file, declare the relationship between the entry point and the notification, that is, the facet.: AOP programmers do it.
Runtime (completed by the Spring framework)
The Spring framework monitors the execution of entry point methods.Once the monitoring to entry point method is run, the agent mechanism is used to dynamically create the agent object of the target object, according to the notification category, in the corresponding location of the agent object, the corresponding function of the notification is organized to complete the complete code logic operation.
In spring, the framework decides which dynamic proxy method to use based on whether the target class implements an interface or not.
XML-based AOP configuration (improves transaction control transfer cases above)
bean.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: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"> <!--To configure AccountService--> <bean id="accountService" class="com.gzgs.service.impl.AccountServiceImpl"> <property name="accountDao" ref="accountDao"></property> </bean> <!--To configure AccountDaoImpl object--> <bean id="accountDao" class="com.gzgs.dao.impl.AccountDaoImpl"> <property name="runner" ref="runner"></property> <!-- injection ConnectionUtils --> <property name="connectionUtils" ref="connectionUtils"></property> </bean> <!--To configure QuueryRunner object--> <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype"> <constructor-arg name="ds" ref="dataSource"></constructor-arg> </bean> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test02"></property> <property name="user" value="root"></property> <property name="password" value="123456"></property> </bean> <!-- To configure Connection Tool class ConnectionUtils --> <bean id="connectionUtils" class="com.gzgs.utils.ConnectionUtils"> <!-- Injection Data Source--> <property name="dataSource" ref="dataSource"></property> </bean> <!-- Configure Transaction Manager--> <bean id="txManager" class="com.gzgs.utils.TransactionManager"> <!-- injection ConnectionUtils --> <property name="connectionUtils" ref="connectionUtils"></property> </bean> <!--To configure AOP--> <aop:config> <!-- Configure entry point expressions id Property specifies the unique identity of the expression. expression Property is used to specify expression content This label is written in aop:aspect Inside the label can only be used for the current cut. It can also be written in aop:aspect Outside, now all facets are available --> <aop:pointcut id="pt1" expression="execution(* com.gzgs.service.impl.*.*(..))"></aop:pointcut> <!--Configure Faces--> <aop:aspect id="advice" ref="txManager"> <!--Configure Pre-Notification--> <aop:before method="beginTransaction" pointcut-ref="pt1"></aop:before> <!--Configure Post Notification--> <aop:after-returning method="commit" pointcut-ref="pt1"></aop:after-returning> <!--Configure exception notifications--> <aop:after-throwing method="rollback" pointcut-ref="pt1"></aop:after-throwing> <!--Configure Final Notification--> <aop:after method="release" pointcut-ref="pt1"></aop:after> </aop:aspect> </aop:config> </beans>
Annotation-based AOP configuration (improves transaction control transfer cases above)
When using annotation-based AOP configurations, there is often a bug in the post-notification execution exception, which is caused by the inconsistency of the calling order of the four notifications: pre-notification, final notification, and post-notification.This results in a post-notification execution failure because the resource is freed, usually with an error message that connection autocommit is not set to false because it is no longer connected to the pre-notification.So when using annotation-based AOP configurations, it is best to use surround notifications to control the order in which programs are executed.
Core AOP Code
Learning Code:https://download.csdn.net/download/weixin_45680962/12550122package com.gzgs.utils; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * Tool class related to transaction management that includes, opening transactions, committing transactions, rolling back transactions, and releasing connections */ @Component("transactionManager") @Aspect public class TransactionManager { @Autowired private ConnectionUtils connectionUtils; @Pointcut("execution(* com.gzgs.service.impl.*.*(..))") private void pt1(){} /** * Open Transaction */ public void beginTransaction(){ try { System.out.println("I'm front"); connectionUtils.getThreadConnection().setAutoCommit(false); }catch (Exception e){ e.printStackTrace(); } } /** * Submit Transaction */ public void commit(){ try { connectionUtils.getThreadConnection().commit(); }catch (Exception e){ e.printStackTrace(); } } /** * Rollback transaction */ public void rollback(){ try { System.out.println("I am an exception"); connectionUtils.getThreadConnection().rollback(); }catch (Exception e){ e.printStackTrace(); } } /** * Release Connection */ public void release(){ try { System.out.println("release"); connectionUtils.getThreadConnection().close();//Return to Connection Pool connectionUtils.removeConnection(); }catch (Exception e){ e.printStackTrace(); } } @Around("pt1()") public Object aroundAdvice(ProceedingJoinPoint pjp){ Object rtValue = null; try { //1. Get parameters Object[] args = pjp.getArgs(); //2. Open Transactions this.beginTransaction(); //3. Execution Method rtValue = pjp.proceed(args); //4. Submit Transaction this.commit(); System.out.println("I'm rear"); //Return results return rtValue; }catch (Throwable e){ //5. Roll back the transaction this.rollback(); throw new RuntimeException(e); }finally { //6. Release resources this.release(); } } }
This blog is purely a personal learning note. The learning resources are from the Black Horse Training Camp. If there are any errors, please correct them.