Good memory is better than bad writing, can write down what, write down what, convenient later consolidation
Spring is introduced
Spring is an open source framework that is a layered JavaEE one-stop framework.
The one-stop framework means that Spring has every layer of solutions that JavaEE develops.
-
The WEB tier: for SpringMVC
-
Service layer: Spring’s Bean management, declarative transactions
-
DAO layer: Spring’s JDBC template, ORM template
Advantages:
-
IOC: Easy to decouple
-
AOP: Extend the program
-
Lightweight framework
-
Easy integration with other frameworks
Spring use
The directory for decompressing the Spring development package is as follows:
-
Docs: Spring development specification and API
-
Libs: Spring JAR package and source code
-
Schema: Constraints on the Spring configuration file
DataAccess is for DataAccess, WEB is for page display, and the core container is the IOC part.
Inversion of Control (IOC)
Inversion of Control refers to an Inversion of creation rights for an object to Spring.
Use IOC will need to import the IOC related packages, the core of the above several packages in the container: beans, the context, the core, expression of four packages.
Realize the principle of
The traditional way to create an object:
UserDAO userDAO=new UserDAO();
Further interface oriented programming can be polymorphic:
UserDAO userDAO=new UserDAOImpl();
The disadvantage of this approach is that the interface and implementation class are highly coupled, and the source code needs to be modified when switching the underlying implementation class. The program design should meet the OCP primitive, and expand the program without modifying the program source code as far as possible. At this point, you can use factory mode:
class BeanFactory{
public static UserDAO getUserDAO(){
return new UserDAOImpl();
}
}
In this way there is no coupling between the interface and the implementation class, but there is coupling between the interface and the factory.
Decoupling is achieved using a factory + reflection + configuration file approach, which is also the underlying implementation of the Spring framework IOC.
// XML configuration file
//
class BeanFactory{
public static Object getBean(String id){
/ / to parse the XML
/ / reflection
Class clazz=Class.forName();
return clazz.newInstance();
}
}
The IOC XML development
The xSD-configuration. HMTL file is included in the docs file. Beans Schema is defined.
The < beans XMLNS = “www.springframework.org/schema/bean…”
XMLNS: xsi = “www.w3.org/2001/XMLSch…”
xsi:schemaLocation=”
www.springframework.org/schema/bean… www.springframework.org/schema/bean…
// Configure the bean here
Call the class:
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(“applicationContext.xml”);
UserService userService=(UserService)applicationContext.getBean(“userService”);
userService.save();
The IOC and DI
DI refers to dependency injection, which requires an IOC environment. Spring manages this class by injecting the properties of the class’s dependencies.
For example, in userServiceImp.java:
public class UserServiceImpl implements UserService{
private String name;
public void setName(String name){
this.name=name;
}
public void save(){
System.out.println(“save “+name);
}
}
In the configuration file:
The < beans XMLNS = “www.springframework.org/schema/bean…”
XMLNS: xsi = “www.w3.org/2001/XMLSch…”
xsi:schemaLocation=”
www.springframework.org/schema/bean… www.springframework.org/schema/bean…
Test code:
@Test
public void demo2(){
// Create a Spring factory
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(“applicationContext.xml”);
UserService userService=(UserService)applicationContext.getBean(“userService”);
userService.save();
}
Running results:
save tony
As you can see, the properties configured in the configuration file have their dependent properties successfully set when Spring manages the class. If you don’t use dependency injection, you can’t use the interface, you have to use the implementation class to set it up, because the interface doesn’t have this property.
Spring’s factory class
-
BeanFactory: An older version of the factory class that generates instances of the class when the getBean() method is called.
-
ApplicationContext: All spring-managed classes are instantiated when the configuration file is loaded. There are two implementation classes:
-
ClassPathXmlApplicationContext: load the classpath configuration file
-
FileSystemXmlApplicationContext: under loading disk configuration file
-
Bean label configuration
-
Id: unique constraint that cannot contain special characters
-
Name: Theoretically repeatable, but preferably not in development. Special characters can appear
Life cycle:
-
Init-method: The method executed when the bean is initialized
-
Destroy-method: The method executed when the bean is destroyed
Scope of action:
-
Scope: The scope of a bean. There are several types of scope, the first two are commonly used
-
Singleton: Created using singleton mode by default
-
Prototype: more cases
-
Request: In a Web project, spring creates a class and stores it in the Request scope
-
Session: In a Web project, spring creates classes and stores them in the Session scope
-
Globalsession: Must be used in a portlet environment in a Web project
-
Property injection Settings
- Constructor – style property injection: The Car class has two properties in the constructor, name and price.
- Set method property injection: The Employee class has two set methods, one for the common type name and the other for the reference type Car (with ref pointing to the id or name of the reference type).
- Attribute injection for the P namespace: first we need to introduce the P namespace:
The < beans XMLNS = “www.springframework.org/schema/bean…”
// Introduce the p namespace
xmlns:p=”www.springframework.org/schema/p”
XMLNS: xsi = “www.w3.org/2001/XMLSch…”
xsi:schemaLocation=”
www.springframework.org/schema/bean… www.springframework.org/schema/bean…
If it is a common property:
If it is a reference type:
<bean id=”employee” class=”demo.Employee” p:name=”xiaoming” p:car-ref:”car”>
- SpEL(Spring Expression Language) Property injection (Spring 3.x later)
- Collection type attribute injection:
qirui
baoma
benchi
Multi-module development configuration
-
When loading a configuration file, load multiple configuration files
-
To introduce multiple configuration files in a configuration file by implementing
IOC annotation development
The sample
-
Introducing JAR packages: In addition to the four packages described above, you will also need to introduce an AOP package.
-
Create ApplicationContext.xml and use annotation development to introduce context constraints (xsD-configuration.html)
The < beans XMLNS = “www.springframework.org/schema/bean…”
XMLNS: xsi = “www.w3.org/2001/XMLSch…”
XMLNS: context = “www.springframework.org/schema/cont…” xsi:schemaLocation=”
www.springframework.org/schema/bean… www.springframework.org/schema/bean…
www.springframework.org/schema/cont… www.springframework.org/schema/cont…
- Component scanning: Developed using IOC annotations, component scanning needs to be configured, that is, which classes under packages use IOC annotations.
<context:component-scan base-package=”demo1″>
-
Add annotations to the class
-
Use annotations to set the value of the property
Property If there is a set method, add the annotation injected by the property to the set method
Attribute has no set method. Add annotations to the attribute.
@Component(“UserDao”)// A class whose ID is UserDao is configured
public class UserDAOImpl implements UserDAO {
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println(“save”);
}
}
Annotations,
- @Component
Component annotations, used to modify a class that Spring manages.
There are three derived annotations that perform similar functions and also modify classes.
-
Controller: Decorates the Web layer class
-
@service: Decorates the Service layer class
-
@repository: Decorates dao layer classes
Property injection
-
Common properties use @value to set the Value of the property
-
Object attributes use @AutoWired, which is an annotation for property injection by type. If you want to inject properties based on the bean name or ID, you need to use @Autowired in conjunction with @Qualifier
-
In real development, @resource (name=” “) is used to complete property injection by object name
3. Other notes
-
@postconstruct is equivalent to init-method and is used to initialize annotations to functions
-
@predestroy is equivalent to destroy-method and is used to destroy the annotation of the function
-
@scope (“prototype”) @scope (“prototype”)
Comparison of XML and annotation development for IOC
-
Application scenario: XML is suitable for any scenario; Annotations are only appropriate for classes that you write, not for classes that you do not provide.
-
You can use XML management beans, using annotations for property injection
AOP development
AOP is the abbreviation of Aspect Oriented Programming, which means section-oriented Programming. It is a kind of technology that realizes unified maintenance of program functions through pre-compilation and run-time dynamic proxy, and it is an extension of OOP.
AOP can enhance the program, without modifying the source code, permission verification, logging, performance monitoring, transaction control, and so on.
In other words, functions are divided into two categories, one is core business functions, and the other is auxiliary enhancement functions. The two classes of functionality are developed independently of each other. For example, the login function is a core business function, and the logging function is a secondary enhancement function. If necessary, log and login can be compiled together. Auxiliary functions are called facets, and this selective, low-coupling approach to programming that combines facets with core business functions is called facets programming.
The underlying implementation
JDK dynamic proxies can only generate proxies for classes that implement interfaces. Cglib dynamic proxies can generate proxy objects for classes that do not implement interfaces, generating subclass objects.
Using the JDK dynamic proxy:
public interface UserDao {
public void insert();
public void delete();
public void update();
public void query();
}
Implementation class:
public class UserDaoImpl implements UserDao { @Override public void insert() { System.out.println(“insert”); } @Override public void delete() { System.out.println(“delete”); } @Override public void update() { System.out.println(“update”); } @Override public void query() { System.out.println(“query”); }}
The JDK agent:
public class JDKProxy implements InvocationHandler{
private UserDao userDao;
public JDKProxy(UserDao userDao){
this.userDao=userDao;
}
public UserDao createProxy(){
UserDao userDaoProxy=(UserDao)Proxy.newProxyInstance(userDao.getClass().getClassLoader(),
userDao.getClass().getInterfaces(), this);
return userDaoProxy;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(“update”.equals(method.getName())){
System.out.println(” permission check “);
return method.invoke(userDao, args);
}
return method.invoke(userDao, args);
}
}
The update function has been enhanced with dynamic proxies. The test class:
public class Demo1 {
@Test
public void demo1(){
UserDao userDao=new UserDaoImpl();
UserDao proxy=new JDKProxy(userDao).createProxy();
proxy.insert();
proxy.delete();
proxy.update();
proxy.query();
}
}
The running results are as follows:
insert
delete
Permission to check
update
query
CglibCglib is a third-party open source generation library that dynamically adds class properties and methods.
Unlike the JDK proxy above, Cglib can be used as follows:
public class CglibProxy implements MethodInterceptor{
// Pass in the enhanced object
private UserDao customerDao;
public CglibProxy(UserDao userDao){
this.userDao=userDao;
}
public UserDao createProxy(){
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(userDao.getClass());
enhancer.setCallback(this);
UserDao proxy=(UserDao)enhancer.create();
return proxy;
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
if(“save”.equals(method.getName())){
System.out.println(“enhance function”);
return methodProxy.invokeSuper(proxy, args);
}
return methodProxy.invokeSuper(proxy, args);
}
}
If the interface classes are implemented, the underlying JDK proxy is used. If it is not a class that implements the interface, the underlying Cglib proxy is used.
Comparison between IOC and traditional methods
- How to get objects: Traditionally, an object is actively created using the new keyword. In IOC mode, the object lifecycle is managed by Spring and objects are obtained directly from Spring. That is, inversion of control ———— takes control out of your hands and gives it to Spring.
AOP development in Spring (AspectJ’s XML approach)
AspectJ is an AOP framework. Spring introduces AspectJ and implements AOP development based on AspectJ.
Related terms
-
Joinpoint: a Joinpoint that can be intercepted. Methods that can be enhanced are join points.
-
Pointcut: The Pointcut, the point that is really intercepted, which is the method that is really enhanced
-
Advice: Enhancement at the method level. Methods that enhance a method, such as permission verification on the save method, are called notifications.
-
Introduction: Class level enhancement.
-
Target: the Target, the enhanced object (class).
-
Weaving: the process of applying advice to target
-
Proxy: a Proxy object that is enhanced.
-
Aspect: a combination of aspects, notifications, and pointcuts.
Method of use
-
Importing related packages
-
Importing a Configuration File
The < beans XMLNS = “www.springframework.org/schema/bean…”
XMLNS: xsi = “www.w3.org/2001/XMLSch…”
xmlns:aop=”www.springframework.org/schema/aop” xsi:schemaLocation=”
www.springframework.org/schema/bean… www.springframework.org/schema/bean…
www.springframework.org/schema/aop www.springframework.org/schema/aop/…
- Write the target class and configure:
public class ProductDaoImpl implements ProductDao {
@Override
public void save() {
System.out.println(“save”);
}
@Override
public void update() {
System.out.println(“update”);
}
@Override
public void find() {
System.out.println(“find”);
}
@Override
public void delete() {
System.out.println(“delete”);
}
}
- Write aspect classes, presumably for permission validation and configuration
public class MyAspectXML {
public void checkPri(){
System.out.println(“check auth”);
}
}
- Enhancements to the target classes are accomplished through an AOP configuration
aop:config
<aop:pointcut expression=”execution(* demo1.ProductDaoImpl.save(..) )” id=”pointcut1″/>
<aop:aspect ref=”myAspect”>
<aop:before method=”chechPri” pointcut-ref=”pointcut1″/>
</aop:aspect>
</aop:config>
Notification type
- Pre-notification: Action before the target method executes to obtain pointcut information
<aop:before method=”chechPri” pointcut-ref=”pointcut1″/>
public void checkPri(JoinPoint joinPoint){
System.out.println(“check auth “+joinPoint);
}
- Post notification: After the target method is executed, the method return value can be obtained
<aop:after-returning method=”writeLog” pointcut-ref=”pointcut2″ returning=”result”/>
public void writeLog(Object result){
System.out.println(“writeLog “+result);
}
- Circular notification: Actions before and after target method execution can prevent target method execution
<aop:around method=”around” pointcut-ref=”pointcut3″/>
public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println(“before”);
Object result=joinPoint.proceed();
System.out.println(“after”);
return result;
}
- Exception throw notification: Action when an exception occurs in the program
<aop:after-throwing method=”afterThrowing” pointcut-ref=”pointcut4″ throwing=”ex”/>
public void afterThrowing(Throwable ex){
System.out.println(“exception “+ex.getMessage());
}
- Final notification: equivalent to a finally block that executes regardless of whether the code has an exception
<aop:after method=”finallyFunc” pointcut-ref=”pointcut4″/>
public void finallyFunc(){
System.out.println(“finally”);
}
- Referral notices: not often used
Spring pointcut expression
Done based on the execution function
Syntax: The package name returned by the access modifier method. Class name. Method name (parameter)
Any field can use * instead of any value
Spring’s AOP is developed based on AspectJ annotations
Development steps
-
The introduction of the jar package
-
Setting up the configuration file:
The < beans XMLNS = “www.springframework.org/schema/bean…”
XMLNS: xsi = “www.w3.org/2001/XMLSch…”
XMLNS: context = “www.springframework.org/schema/cont…”
xmlns:aop=”www.springframework.org/schema/aop”
xmlns:tx=”www.springframework.org/schema/tx”
Xsi: schemaLocation = “HTTP: / / www.springframework.org/schema/bean…
www.springframework.org/schema/bean…
www.springframework.org/schema/cont…
www.springframework.org/schema/cont…
www.springframework.org/schema/aop
www.springframework.org/schema/aop/…
www.springframework.org/schema/tx
www.springframework.org/schema/tx/s…
- Write the configuration target class
public class OrderDao {
public void save(){
System.out.println(“save order”);
}
public void update(){
System.out.println(“update order”);
}
public void delete(){
System.out.println(“delete order”);
}
public void find(){
System.out.println(“find order”);
}
}
- Enable aop annotation automatic proxy
aop:aspectj-autoproxy/
- Write the aspect class and configure it
@Aspect
public class MyAspectAnno {
@Before(value=”execution(* demo1.OrderDao.save(..) )”
public void before(){
System.out.println(“before”);
}
}
Annotation notification type
-
@before: Pre-notification
-
@afterreturning: Post notification
@AfterReturning(value=”execution(* demo1.OrderDao.save(..) )”,returning=”result”)
public void after(Object result){
System.out.println(“after “+result);
}
- @around: Circular notification
@Around(value=”execution(* demo1.OrderDao.save(..) )”
public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println(“before”);
Object obj=joinPoint.proceed();
System.out.println(“after”);
return obj;
}
- @afterThrowing: Throws an exception
@AfterThrowing(value=”execution(* demo1.OrderDao.save(..) )”,throwing=”e”)
public void afterThrowing(Throwable e){
System.out.println(“exception:”+e.getMessage();
}
- @after: Final notice
@After(value=”execution(* demo1.OrderDao.save(..) )”
public void after(){
System.out.println(“finally”);
}
- PointCut: PointCut annotations
@PointCut(value=”execution(* demo1.OrderDao.save(..) )”
private void pointcut1(){}
At this point, in the comments of the above notice, value can be replaced by the function name, for example:
@After(value=”MyAspect.pointcut1()”)
public void after(){
System.out.println(“finally”);
}
The advantage of this annotation is that you only need to maintain the pointcut, and you don’t need to modify each annotation as you modify it.
Spring’s JDBC template
Spring also provides solutions for the persistence layer, namely ORM modules and JDBC templates. For JDBC, provides the org. Springframework. JDBC. Core. The JdbcTemplate as template class.
Using JDBC Templates
-
Introduce JAR packages, database drivers, and Spring jDBC-related packages.
-
Basic use:
public void demo1(){
// Create a connection pool
DriverManagerDataSource dataSource=new DriverManagerDataSource();
dataSource.setDriverClassName(“com.mysql.jdbc.Driver”);
dataSource.setUrl(“jdbc:mysql:///spring4”);
dataSource.setUsername(“root”);
dataSource.setPassword(“123456”);
// Create a JDBC template
JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
jdbcTemplate.update(“insert into account values (null,? ,?) “, “xiaoming”,1000d);
}
- Hand over connection pooling and templates to Spring for management
- Configuration file:
- Test file:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(“classpath:applicationContext.xml”)
public class JdbcDemo2 {
@Resource(name=”jdbcTemplate”)
private JdbcTemplate jdbcTemplate;
@Test
public void demo2(){
jdbcTemplate.update(“insert into account values (null,? ,?) “, “xiaolan”,1000d);
}
}
Use open source database connection pools
- Configuration using DBCP:
- Using C3P0 configuration:
- Import external properties files
Create the external properties file first:
jdbc.driverClass=com.mysql.jdbc.Driver
The JDBC url = JDBC: mysql: / / 192.168.66.128 / spring4
jdbc.username=root
jdbc.password=123456
Then configure the properties file:
<context:property-placeholder location=”classpath:jdbc.properties”/>
CRUD operations
Insert, UPDATE, and DELETE statements all operate with the help of the template’s UPDATE method.
public void demo(){
jdbcTemplate.update(“insert into account values (null,? ,?) “, “xiaoda”,1000d);
jdbcTemplate.update(“update account set name=? ,money=? where id=?” , “xiaoda”,1000d,2);
jdbcTemplate.update(“delete from account where id=?” , 6);
}
Query operation:
public void demo3(){
String name=jdbcTemplate.queryForObject(“select name from account where id=?” ,String.class,5);
long count=jdbcTemplate.queryForObject(“select count(*) from account”,Long.class);
}
Encapsulate the returned result as a class:
public void demo4(){
Account account=jdbcTemplate.queryForObject(“select * from account where id=?” , new MyRowMapper(),5);
}
Among them:
class MyRowMapper implements RowMapper{
@Override
public Account mapRow(ResultSet rs, int rowNum) throws SQLException {
Account account=new Account();
account.setId(rs.getInt(“id”));
account.setName(rs.getString(“name”));
account.setMoney(rs.getDouble(“money”));
return account;
}
}
Spring transaction management
The transaction
A transaction is a logical set of operations in which the units that make up the operation either all succeed or all fail.
It has four characteristics:
-
Atomicity: Transactions are indivisible
-
Consistency: Data integrity remains consistent before and after a transaction is executed
-
Isolation: The execution of a transaction should not be interrupted by other transactions
-
Persistence: Data is persisted to the database once the transaction ends
Security issues arise if isolation is not considered:
-
Read the questions:
-
Dirty read: a transaction reads uncommitted data from another transaction
-
Non-repeatable read: A transaction reads update data that has been committed by another transaction, resulting in inconsistent results for multiple queries in one transaction
-
Phantom read: a transaction reads insert data already committed by another transaction, resulting in inconsistent results for multiple queries within a transaction
-
-
Write questions:
- Lost update
Resolve read problems: Set transaction isolation level
-
Read uncommitted: No Read problem can be solved
-
Read COMMITTED: Indicates that Read is committed to solve dirty Read problems
-
Repeatable Read: Solves the problems of dirty and unrepeatable read
-
Serializable: serializes all read issues
Transaction Management API
- PlatformTransactionManager: the platform transaction manager
This is an interface, with a number of different implementation classes, such as DataSourceTransactionManager underlying use JDBC management affairs; HibernateTransactionManager underlying use Hibernate management affairs.
- TransactionDefinition: TransactionDefinition information
Used to define information about a transaction, such as isolation level, timeout information, propagation behavior, whether it is read-only, and so on
- TransactionStatus: TransactionStatus
An object used to record the state of a transaction during transaction management.
When Spring conducts transaction management, the platform transaction manager firstly performs transaction management according to the transaction definition information. In the process of transaction management, various states are generated and these state information is recorded in the object of transaction state.
Propagation behavior of transactions
The propagation behavior of transactions mainly solves the problem of Service invocation, that is, how to operate when different transactions exist in different businesses.
Spring provides seven types of transaction propagation behavior, divided into three categories:
-
Ensure multiple operations are in the same transaction
-
5, PROPAGATION_REQUIRED: The B method calls A method, and if A has A transaction, uses the transaction in A and includes the operations in B in that transaction. Otherwise, create A new transaction that includes the operations in A and B. (the default)
-
PROPAGATION_SUPPORTS: If A has A transaction, use A’s transaction. Otherwise, transactions are not used
-
PROPAGATION_MANDATORY: If A has A transaction, use A’s transaction. Otherwise throw an exception
-
-
Ensure that multiple operations are not in the same transaction
-
PROPAGATION_REQUIRES_NEW: If there is A transaction in A, suspend it and create A new transaction that contains only its own operations. Otherwise, create a new transaction that contains only its own operations.
-
5, PROPAGATION_NOT_SUPPORTED: If A has A transaction, suspend, no transaction is used.
-
PROPAGATION_NEVER: If A has A transaction, throw an exception, meaning that A transaction cannot be run.
-
-
The nested transaction
- Execute A transaction, PROPAGATION_NESTED: If A has A transaction, execute A transaction, and set A savepoint, and execute B’s operation. If an exception occurs, you can roll back to the original state or savepoint state.
The instance
Take transfer as an example, the DAO layer of the business layer is as follows:
public interface AccountDao {
public void outMoney(String from,Double money);
public void inMoney(String to,Double money);
}
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao{
@Override
public void outMoney(String from, Double money) {
this.getJdbcTemplate().update(“update account set money = money – ? where name = ?” ,money,from);
}
@Override
public void inMoney(String to, Double money) {
this.getJdbcTemplate().update(“update account set money = money + ? where name = ?” ,money,to);
}
}
public interface AccountService {
public void transfer(String from,String to,Double money);
}
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public void transfer(String from, String to, Double money) {
accountDao.outMoney(from, money);
accountDao.inMoney(to, money);
}
}
Configuring classes in XML:
Transaction Management 1: Programmatic transaction management
- Configure the platform transaction manager
- Configure the transaction management template class
- Inject transaction management templates at the business layer
- The code implements transaction management
/ / ServiceImpl class:
private TransactionTemplate transactionTemplate;
@Override
public void transfer(String from, String to, Double money) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus arg0) {
accountDao.outMoney(from, money);
accountDao.inMoney(to, money);
}
});
}
Declarative transaction management (configured implementation, AOP based)
- Declarative transaction management in XML
- Configure the transaction manager
- Configuring transaction Notification
<tx:advice id=”txAdvice” transaction-manager=”transactionManager”>
tx:attributes
<tx:method name=”transfer” propagation=”REQUIRED”/>
</tx:attributes>
</tx:advice>
- Configuring AOP Transactions
aop:config
<aop:pointcut expression=”execution(* tx.demo2.AccountServiceImpl.*(..) )” id=”pointcut1″/>
<aop:advisor advice-ref=”txAdvice” pointcut-ref=”pointcut1″/>
</aop:config>
- Annotation way
-
Configure the transaction manager, as above
-
Note to enable transaction management:
<tx:annotation-driven transaction-manager=”transactionManager”/>
- Add a annotation @Transactional on classes that use transactions
The content that still has later, go to complement again!
Article address: mp.weixin.qq.com/s?__biz=MzU…