catalogue
3, Five types of notifications are implemented in three ways
2. Declaring a Pointcut simplifies the above code
1. Configure maven repository (pom.xml)
4. Class to create database (student)
1, Foreword
Before talking about Spring's AOP, let's talk about whether our transaction should be completed in one layer. Should it be completed in Dao (data access layer) or service (business layer)?
Obviously, we should complete the transaction at the business level. For example, bank transfer is a transaction. It can be said that a transaction is completed only when one party completes the transfer and the other party completes the collection. If our transaction cannot be completed due to special circumstances, we must roll back and restore the original state, However, is it easy to cause redundancy to complete such public operations in the business layer as before? Therefore, Spring's AOP wants to peel off all common codes and place them separately in a class for centralized management. During the specific run time, these public codes are dynamically woven by the container.
From the official explanation: AOP (aspect oriented programming), it is a technology that can dynamically and uniformly add functions to the program without modifying the source code through precompile and runtime dynamic agent.
So let's use a dynamic proxy to implement how to split the public code
proxy class
import java.lang.reflect.Proxy; import java.util.Arrays; import org.junit.Test; import com.DJX.Dao.UserDao; import com.DJX.Dao.Impl.UserDaoImpl; public class UserProxyTest { @Test public void testProxy() { UserDaoImpl userDaoImpl = new UserDaoImpl(); Class[]clazz=userDaoImpl.getClass().getInterfaces(); System.out.println(Arrays.toString(clazz)); UserDao userdao = (UserDao) Proxy.newProxyInstance(UserProxyTest.class.getClassLoader(), clazz, new MyHandeler(userDaoImpl)); /* Classes Gets the number of interfaces of the object NewProxyInstance To create an agent, the three parameters are class loader, interface and implementation interface InvocationHandler */ System.out.println(userdao.hashCode()); userdao.add(); int res =userdao.addUser("Zhang San"); //Every time a method is called, the proxy's invoke will be called. addUser is the method, and "Zhang San" is args. At this time, myhandler is like a monitor to monitor the request proxy object at all times. System.out.println(res); } }
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.util.Arrays; public class MyHandeler implements InvocationHandler{ Object target; public MyHandeler(Object target) { // TODO Auto-generated constructor stub this.target=target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub System.out.println(method+"\t"+Arrays.toString(args)); Object res = method.invoke(target, args); return res; } }
Draw a picture to help understand
2, Several concepts in AOP
1. Connection point: those methods in the class can be enhanced. These methods are called connection points (@ pointcut is the connection point)
2. Pointcuts: the methods that are actually enhanced are called pointcuts
Such as execution(* com.DJX.Dao. *. * (..))
The * sign in the first part indicates any return value
The second part * sign com.DJX.Dao. * indicates any class under the com.DJX.Dao package
The * sign in the third part indicates any method under any class
The fourth part (..) represents the number of arbitrary parameters
3. Notification: the so-called notification refers to the code to be executed after intercepting the connection point. Notifications are divided into five categories: pre, post, exception, final and surround notifications
4. Aspect: action, the process of applying notification to the pointcut, which is implemented using the @ aspect class
3, Five types of notifications are implemented in three ways
1. Annotation implementation
First, set the xml file, scan the basic package, and set the < AOP: AspectJ AutoProxy > otherwise, annotations will not have an effect
<context:component-scan base-package="com.DJX"></context:component-scan> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
The data link layer writing method is left to Spring for management
import org.springframework.stereotype.Repository; @Repository public class UserDao { public void add() { System.out.println("UserDao of add method"); } public void save() { System.out.println("UserDao of save()method"); // System.out.println(1/0); } }
Proxy class required
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Component//Basic class @Aspect public class UserProxy { @Before(value="execution(* com.DJX.Dao.UserDao.save(..))") //Annotation is executed before * indicates whether it is returned, com.DJX.Dao.UserDao package name, save method, (..) parameter public void before() { System.out.println("Before method execution...."); } @After(value="execution(* com.DJX.Dao.UserDao.save(..))")//Post notification public void after() { System.out.println("After method execution...."); } @AfterReturning(value="execution(* com.DJX.Dao.UserDao.save(..))")//Final notice public void afterReturning() { System.out.println("Final notice"); } @AfterThrowing(value="execution(* com.DJX.Dao.UserDao.save(..))") public void afterthow() { System.out.println("Exception notification"); } @Around(value="execution(* com.DJX.Dao.UserDao.save(..))")//Around Advice public void around(ProceedingJoinPoint p) { try { System.out.println("surround-Front"); p.proceed(); System.out.println("surround-Post"); } catch (Throwable e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
Effect display
2. Declaring a Pointcut simplifies the above code
Modify the proxy class
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Component//Basic class @Aspect public class UserProxy { @Pointcut(value="execution(* com.DJX.Dao.UserDao.save(..))") public void point() { } //@Before(value="execution(* com.DJX.Dao.UserDao.save(..))") @Before(value="point()") //Annotation is executed before * indicates whether it is returned, com.DJX.Dao.UserDao package name, save method, (..) parameter public void before() { System.out.println("Before method execution...."); } //@After(value="execution(* com.DJX.Dao.UserDao.save(..)") / / post notification @After(value="point()")//Post notification public void after() { System.out.println("After method execution...."); } //@AfterReturning(value="execution(* com.DJX.Dao.UserDao.save(..)") / / final notification @AfterReturning(value="point()")//Final notice public void afterReturning() { System.out.println("Final notice"); } @AfterThrowing(value="execution(* com.DJX.Dao.UserDao.save(..))") public void afterthow() { System.out.println("Exception notification"); } //@Around(value="execution(* com.DJX.Dao.UserDao.save(..)") / / surround notification @Around(value="point()")//Around Advice public void around(ProceedingJoinPoint p) { try { System.out.println("surround-Front"); p.proceed(); System.out.println("surround-Post"); } catch (Throwable e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
3. By configuration
Configuration file xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" 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-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:component-scan base-package="com.DJX"></context:component-scan> <bean id="proxy" class="com.DJX.Proxy.UserProxy2"></bean> <aop:config> <aop:pointcut expression="execution(* com.DJX.Dao.UserDao.save(..))" id="point"/> <aop:aspect ref="proxy"> <aop:before method="before" pointcut-ref="point"/> <aop:around method="around" pointcut-ref="point"/> <aop:after method="after" pointcut-ref="point"/> </aop:aspect> </aop:config> </beans>
Because of the configuration file, comments are not required
proxy class
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Component//Basic class @Aspect public class UserProxy2 { //Annotation is executed before * indicates whether it is returned, com.DJX.Dao.UserDao package name, save method, (..) parameter public void before() { System.out.println("Before method execution...."); } public void after() { System.out.println("After method execution...."); } public void afterReturning() { System.out.println("Final notice"); } public void afterthow() { System.out.println("Exception notification"); } public void around(ProceedingJoinPoint p) { try { System.out.println("surround-Front"); p.proceed(); System.out.println("surround-Post"); } catch (Throwable e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
Effect display
4, Spring integrates jdbc
1. Configure maven repository (pom.xml)
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.3.9</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-tx --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.3.8</version> </dependency>
2. Add database profile
3. Introduction of database
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" 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-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:component-scan base-package="com.DJX"></context:component-scan><!-- scanning com.DJX File under package --> <context:property-placeholder location="classpath:druid.properties"/><!-- Load profile --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><!-- Create database pool --> <property name="driverClassName" value="${jdbc.driverClassName}"></property> <property name="url" value="${jdbc.url}"></property> <property name="username" value="${jdbc.name}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!-- Injection data source --> <bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> </beans>
4. Class to create database (student)
import lombok.Data; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; //@Data @Getter @Setter @NoArgsConstructor public class Student { @Override public String toString() { return "Student [id=" + id + ", name=" + name + ", password=" + password + "]"; } private Integer id; private String name; private String password; public Student(String name,String password) { this.name=name; this.password=password; } }
5. Add method
import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; import com.DJX.bean.Student; @Repository//Leave it to Spring to manage, so you need to scan and add the Repository public class StudentDao { @Autowired//Automatic injection private JdbcTemplate jdbcTemplate; public int add(Student student) { return jdbcTemplate.update("insert into student (NAME,PASSWORD) VALUES(?,?)",student.getName(),student.getPassword()); } }
Test class
import org.junit.BeforeClass; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.DJX.Dao.StudentDao; import com.DJX.bean.Student; //@BeforeClass, execute it before all methods, and after class, execute it after all methods are executed //@before calls it once before each method is executed. public class StudentTest { static StudentDao studentdao; @BeforeClass public static void init() { ApplicationContext context=new ClassPathXmlApplicationContext("bean2.xml");//Parsing xml studentdao = context.getBean(StudentDao.class); } @Test public void test() { Student student = new Student("Wang Wu", "123456789");//create object ApplicationContext context=new ClassPathXmlApplicationContext("bean2.xml");//Parsing xml StudentDao studentdao = context.getBean(StudentDao.class); studentdao.add(student); } }
6. Delete function
import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; import com.DJX.bean.Student; @Repository//Leave it to Spring to manage, so you need to scan and add the Repository public class StudentDao { @Autowired//Automatic injection private JdbcTemplate jdbcTemplate; public int delete(int id) { return jdbcTemplate.update("delete from student where id=?",id); } }
Test class
import org.junit.BeforeClass; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.DJX.Dao.StudentDao; import com.DJX.bean.Student; //@BeforeClass, execute it before all methods, and after class, execute it after all methods are executed //@before calls it once before each method is executed. public class StudentTest { static StudentDao studentdao; @BeforeClass public static void init() { ApplicationContext context=new ClassPathXmlApplicationContext("bean2.xml");//Parsing xml studentdao = context.getBean(StudentDao.class); } @Test public void test() { int d=studentdao.delete(2); System.out.println(d>0?"Delete succeeded":"Deletion failed"); } }
7. Find function
import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; import com.DJX.bean.Student; @Repository//Leave it to Spring to manage, so you need to scan and add the Repository public class StudentDao { @Autowired//Automatic injection private JdbcTemplate jdbcTemplate; public List<Student> selectObject(){ return jdbcTemplate.query("select * from student where name like ?", new BeanPropertyRowMapper<Student>(Student.class),"Lee%"); } }
Test class
import java.util.List; import org.junit.BeforeClass; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.DJX.Dao.StudentDao; import com.DJX.bean.Student; //@BeforeClass, execute it before all methods, and after class, execute it after all methods are executed //@before calls it once before each method is executed. public class StudentTest { static StudentDao studentdao; @BeforeClass public static void init() { ApplicationContext context=new ClassPathXmlApplicationContext("bean2.xml");//Parsing xml studentdao = context.getBean(StudentDao.class); } @Test public void test() { List<Student> list =studentdao.selectObject(); // System.out.println(list); for(Student l:list) { System.out.println(l); } } }
8. Modify function
import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; import com.DJX.bean.Student; @Repository//Leave it to Spring to manage, so you need to scan and add the Repository public class StudentDao { @Autowired//Automatic injection private JdbcTemplate jdbcTemplate; public int alters(String name,int id) { return jdbcTemplate.update("update student set name=? where id=?",name,id); } }
Test class
import org.junit.BeforeClass; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.DJX.Dao.StudentDao; import com.DJX.bean.Student; //@BeforeClass, execute it before all methods, and after class, execute it after all methods are executed //@before calls it once before each method is executed. public class StudentTest { static StudentDao studentdao; @BeforeClass public static void init() { ApplicationContext context=new ClassPathXmlApplicationContext("bean2.xml");//Parsing xml studentdao = context.getBean(StudentDao.class); } @Test public void test() { int d=studentdao.alters("Debang", 3); System.out.println(d>0?"Modified successfully":"Modification failed"); } }