Part I Overview of Spring

1 introduction of Spring

Spring is a hierarchical full-stack lightweight open source framework based on IoC and AOP. It provides many enterprise-level application technologies such as SpringMVC at the presentation layer and transaction management at the business layer. Spring official address: https://spring.io/

2. Development history of Spring

  • 1997-2006 EJB1.0-EJB3.0 was released
  • In 2002, Expert One-To-one J2EE Design and Development explained the advantages and solutions of J2EE Development and Design using EJB
  • 2004 Expert one-to-one J2EE Development without EJB

3. Advantages of Spring

  • Decouple and simplify development

With the IoC container provided by Spring, dependencies between objects can be left to Spring to control, avoiding excessive program coupling caused by hard coding (New).

  • Support for AOP programming

Spring’s AOP capabilities make it easy to do section-oriented programming, and many of the features that aren’t easy to implement with traditional OOP can be easily handled with AOP

  • Support for declarative transactions

Transactional @Transactional takes you away from tedious transaction management code and allows you to manage transactions in a declarative and flexible way to improve development efficiency and quality

  • Convenience test

  • Easy integration of various excellent frameworks

Spring makes it easier to use all kinds of frameworks and provides direct support for all kinds of great frameworks

  • Reduce the difficulty of using JavaEE apis

Spring’s thin encapsulation of javaEE apis makes them much easier to use

  • Source code is a classic Java learning paradigm

Spring’s source code is well designed and well structured, demonstrating Event’s flexible use of Java design patterns and deep knowledge of Java technology.

4. Spring’s core structure

The second part is the core idea

1. IoC

1.1 What is IoC?

He is a technical idea, not a technical implementation

  • Traditional development: Class A depends on class B and new an object of B in class A
  • Development with IoC in mind: instead of creating new objects ourselves, the IoC container (the Spring framework) helps us instantiate objects and manage them, and we ask the IoC container which objects we need to use

Why is it called inversion of control

  • Control: Refers to the right to create (instantiate, manage) objects
  • Reverse: Transfer control to the external environment (Spring framework, IoC container)

1.2 Problems solved by IoC: coupling between objects

1.3 Difference between IoC and DI

  • The IoC container is standing onObject AngleThe object instantiation machine management is given (reversed) to the container
  • DI is standingAngle of containerWill inject other objects that the object depends on

2. AOP

2.1 What is AOP

AOP: Aspect oriented programming/aspect oriented programming, AOP is a continuation of OOP.

What are the problems with crosscutting logic code:

  • Crosscutting code duplication
  • Crosscutting logic code is mixed with business code, which is bloated and difficult to maintain

AOP proposes horizontal extraction, separating crosscutting logic code from business logic code

2.2 What problem is AOP solving

In the case of not changing the original business logic, enhance the cross-cutting logic code, fundamentally decouple, avoid cross-cutting logic code repetition

2.3 Why is it called faceted Programming

Cutting: refers to the crosscutting logic. The original business logic code cannot move, but can only operate the crosscutting logic code, so it faces the crosscutting logic plane: the crosscutting logic code often affects many methods, each method is like a point, and multiple points form the plane.

The third part handwritten IoC and AOP

Based on review of

-a Simple factory mode

The sample code

public interface INoodles {
    
    /** * describe the noodles */
    void desc(a);
}

public class LaMian implements INoodles {
    @Override
    public void desc(a) {
        System.out.println("A bowl of ramen from Lanzhou"); }}public class PaoMian implements INoodles {
    @Override
    public void desc(a) {
        System.out.println("A bowl of instant noodles from the supermarket."); }}public class DanDanMian implements INoodles {
    @Override
    public void desc(a) {
        System.out.println("A bowl of Dan Dan noodles from Sichuan."); }}public class SimpleNoodlesFactory {
    
    public static final int LM = 1;
    public static final int PM = 2;
    public static final int DDM = 1;
    
    public static INoodles createNoodles(int noodleType) {
        switch (noodleType) {
            case 1:
                return new LaMian();
            case 2:
                return new PaoMian();
            case 3:
                return new DanDanMian();
            default:
                return null; }}}Copy the code

– B Indicates the singleton mode

  • Villian mode
public class HungrySingleton {
    
    // Privatize the constructor (a necessary step for the singleton)
    private HungrySingleton(a) {}
    // Set the self-instantiated object to a property, with static and final
    private static final HungrySingleton instance = new HungrySingleton();
    // The static method returns the instance
    public static HungrySingleton getInstance(a) {
        returninstance; }}Copy the code
  • Lazy mode
public class LazySingleton {
    // Privatize the constructor
    private LazySingleton(a) {}
    // Set the self-instantiated object to a property and decorate it with static
    private static LazySingleton instance;
    Static method returns the instance with the synchronized keyword.
    public static synchronized LazySingleton getInstance(a) {
        if(instance == null) {
            instance = new LazySingleton();
        }
        returninstance; }}Copy the code

3.1 Bank Transfer Case (key code)

  • servlet
@WebServlet(name="transferServlet",urlPatterns = "/transferServlet")
public class TransferServlet extends HttpServlet {
    // 1. Instantiate the Service layer object
    private TransferService transferService = new TransferServiceImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
    doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse
resp) throws ServletException, IOException {
    // Sets the character encoding of the request body
    req.setCharacterEncoding("UTF-8");
    String fromCardNo = req.getParameter("fromCardNo");
    String toCardNo = req.getParameter("toCardNo");
    String moneyStr = req.getParameter("money");
    int money = Integer.parseInt(moneyStr);
    Result result = new Result();
    try {
        // 2. Call the service layer method
        transferService.transfer(fromCardNo,toCardNo,money);
        result.setStatus("200");
    } catch (Exception e) {
        e.printStackTrace();
        result.setStatus("201");
        result.setMessage(e.toString());
        }
    / / response
    resp.setContentType("application/json; charset=utf-8");
    resp.getWriter().print(JsonUtils.object2Json(result));
}
Copy the code
  • TransferService Interface and implementation class
public class TransferServiceImpl implements TransferService {
    private AccountDao accountDao = new JdbcAccountDaoImpl();
    @Override
    public void transfer(String fromCardNo, String toCardNo, int money)throws Exception {
        Account from = accountDao.queryAccountByCardNo(fromCardNo);
        Account to = accountDao.queryAccountByCardNo(toCardNo);
        from.setMoney(from.getMoney()-money);
        to.setMoney(to.getMoney()+money);
        accountDao.updateAccountByCardNo(from);
        accountDao.updateAccountByCardNo(to);
    }
Copy the code
  • AccountDao layer interface and JDBC-based implementation class
public class JdbcAccountDaoImpl implements AccountDao {
    @Override
    public Account queryAccountByCardNo(String cardNo) throws Exception {
    // Get the connection from the connection pool
        Connection con = DruidUtils.getInstance().getConnection();
        String sql = "select * from account where cardNo=?";
        PreparedStatement preparedStatement = con.prepareStatement(sql);
        preparedStatement.setString(1,cardNo);
        ResultSet resultSet = preparedStatement.executeQuery();
        Account account = new Account();
        while(resultSet.next()) {
            account.setCardNo(resultSet.getString("cardNo"));
            account.setName(resultSet.getString("name"));
            account.setMoney(resultSet.getInt("money"));
        }
        resultSet.close();
        preparedStatement.close();
        con.close();
        return account;
    }
    @Override
    public int updateAccountByCardNo(Account account) throws Exception {
    // Get the connection from the connection pool
        Connection con = DruidUtils.getInstance().getConnection();
        String sql = "update account set money=? where cardNo=?";
        PreparedStatement preparedStatement = con.prepareStatement(sql);
        preparedStatement.setInt(1,account.getMoney());
        preparedStatement.setString(2,account.getCardNo());
        int i = preparedStatement.executeUpdate();
        preparedStatement.close();
        con.close();
        returni; }}Copy the code

3.2 Analysis of bank transfer cases

3.3 Solutions

  • thinking
  1. The new keyword couples the Service layer’s implementation class TransferServiceImpl with the Dao layer’s concrete implementation class JdbcAccountDapImpl and can be used in addition to newReflection class.forname (" fully qualified Class name ");Fully qualified class names can be configured in early XML
  2. Using factories to produce objects using reflection techniques, factory patterns are a great way to decouple
  3. The service layer does not add transaction control to manually control JDBC Connection transactions, but make sure that Connection is bound to the current thread.

3.4 Code Optimization

Part four: Spring IoC applications

4.1 Fundamentals of Spring IoC

4.1.1 Difference between BeanFactory and ApplicationContext

BeanFactory is the top interface of the IoC container in the Spring framework. It is used to define basic functions and basic specifications. ApplicationContext is one of its subinterfaces. So the ApplicationContext has all the functionality provided by the BeanFactory. Usually, we call the BeanFactory the base container of SpringIoc. ApplicationContext is the high-level interface of the container and has more functionality than BeanFactory.

How to start the IoC container

  • Start the IoC container in Java
    1. ClassPathXmlApplicationContext: from the root class shelf configuration file
    2. FileSystemXmlApplicationContext: load the configuration file from the disk path
    3. Start the Spring container AnnotationConfigApplicationContext: pure annotation mode
public class IoCTest {
    @Test
    public void testIoC(a){
        // Start the container by reading the XML file in the classpath (recommended for XML schema SE applications)
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        // Load the configuration file from the disk path
        ApplicationContext applicationContext1 = new FileSystemXmlApplicationContext("Absolute file path");
        AccountDao accountDao = (AccountDao) applicationContext.getBean("accountDao");
        //System.out.println(accountDao);
        Object connectionUtils = applicationContext.getBean("connectionUtils"); System.out.println(connectionUtils); }}Copy the code
  • Start the IoC container in the Web environment
    1. Start the container from XML
<! DOCTYPEweb-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <! Configure the SpringIoC container configuration file -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>
  <! Start IoC container with listener -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
</web-app>
Copy the code

4.1.2 Pure XML schema

  • XML file header

Multiple Spring component label profiles can be configured, distinguished by prefixes

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/beans/spring-aop.xsd ">
Copy the code
  • Three ways to instantiate beans
  1. Using the no-argument constructor By default, objects are created by calling the no-argument constructor through reflection. If the class does not have a no-argument constructor, the creation fails

applicationContext.xml

<bean id="connectionUtils" class="cn.percent.utils.ConnectionUtils"/>
Copy the code
  1. Create using static methods

In development, we use objects that are not directly created by constructors, and may do a lot of extra work during creation. This is the case when a method is provided to create an object that happens to be static. Such as: Connection implementation class. If mysql database is used, JDBC4Connection is used. But we’re not going to write JDBC4Connection connection = new JDBC4Connection (), because we want to register drive, but also provide the URL and confidential information, with the DriverManager. The getConnection method to get the connection.

applicationContext.xml

<bean id="connectionUtils" class="cn.percent.factory.CreateBeanFactory" factory-method="getInstanceStatic"/>
Copy the code
  1. Create using the instantiation method

This method is similar to static method creation, except that the method used to get the object is no longer a static modifier, but a normal method in the class. This method is more likely to be used than static method creation.

<bean id="createBeanFactory" class="cn.percent.factory.CreateBeanFactory"></bean>
<bean id="connectionUtils" factory-bean="createBeanFactory" factory-method="getInstance"></bean>
Copy the code
  • The life cycle of the Bean
  1. Scope of action changed

When the Spring framework manages the creation of Bean objects, Bean objects are singletons by default, but they are configurable in a way that changes scope.

<! -- Configure service object -->
<bean id="transferService" class="com.lagou.service.impl.TransferServiceImpl" scope="singleton"/>
Copy the code

Singleton object birth: When the container is created, the object is created. Object alive: As long as the container is there, the object is destroyed. Object death: When the container is destroyed, the object is destroyed. Object birth: When an object is used, a new instance of the object is created. Object alive: An object is alive as long as it is in use. Object death: When an object is not used for a long time, it is collected by the Java garbage collector. The Spring framework is only responsible for creating, not destroying, multi-instance bean objects

  1. Bean label properties
attribute explain
id Used to provide a unique identity to the bean. Within a label, the identity must be unique.
class Used to specify the fully qualified class name to create the Bean object.
name Use to give the bean one or more names. Multiple names are separated by Spaces.
factory-bean Used to specify the unique identity of the factory bean that created the current bean object. When this property is specified, the class property becomes invalid.
factory-method Used to specify the factory method used to create the current bean object. If used with the factory-bean property, the class property is invalid. To be used with the class attribute, the method must be static.
scope Used to specify the scope of the bean object. Usually it’s a singleton. You can set it to Prototype when you want to use multi-example patterns.
init-method The initialization method used to specify the bean object, which is called after the bean object is assembled. Must be a no-parameter method.
destory-method Used to specify the bean object’s destruction method, which is executed before the bean object is destroyed. It only works if scope is a Singleton
  1. DI XML configuration for dependency injection
  • Dependency injection classification

(1). Constructor injection: use the constructor with parameters to achieve the data assignment of class members.

   <bean id="accountDao" class="cn.percent.dao.impl.JdbcAccountDaoImpl">
        <! --name: insert by parameter name, index: insert by parameter position -->
        <constructor-arg name="connectionUtils" ref="connectionUtils"></constructor-arg>
        <constructor-arg name="name" value="zhangsan"></constructor-arg>
        <constructor-arg name="sex" value="1"></constructor-arg>
        <constructor-arg name="money" value="100.6"></constructor-arg>
   </bean>
Copy the code

(2).set method injection

  • Basic types and Strings

<property name="name" value="zhangsan"></property>

  • Other Bean types

<property name="ConnectionUtils" ref="connectionUtils"></property>

  • Complex types (collection types)

The injected data type is one of Array, List, Set, Map, and Properties

<property name="myMap">
    <map>
       <entry key="key1" value="value1"></entry>
       <entry key="key2" value="value2"></entry>
       <entry key="key3" value="value3"></entry>
    </map>
</property>
Copy the code

4.1.3 Schema to be combined with XML and annotations

XML form Corresponding annotation form
The label @Component(“accountDao”), annotation The bean ID attribute content added to the class is configured directly after the annotation. If not, the bean ID is defined as lowercase by default. In addition, for hierarchical code development to provide @Componenet three aliases @Controller, @Service, @Repository are respectively used to control layer class, Service layer class, DAO layer class bean definition, the usage of these four annotations is exactly the same, just for a clearer distinction
The scope attribute of the tag @scope (“prototype”), default singleton, annotation added to class
The initMethod property of the tag @postconstruct, the annotation is placed on the method that is called after initialization
Destorymethod property of the tag @predeStory, annotation to the method that was called before destruction
  • DI DI @autowired annotation way (recommended), the @autowired annotation for the Spring, you need to import the package org. Springframework. Beans. Factory. The annotation. Autowired. The @AutoWired strategy is injection by type. When a type has multiple BEAb values, there is no way to choose which one to inject. Use this parameter with @qualifier
public class TransferServiceImpl implements TransferService {

    //Autowired is injected by type. If an object cannot be uniquely locked by type, specify it in conjunction with Qualifier
    @Autowired
    @Qualifier("accountDao")
    private AccountDao accountDao;
}
Copy the code

4.1.4 Pure annotation method

Remove the configuration from THE XML and start from the Java configuration class with the corresponding annotation: The current class is a Configuration class @ComponentScan annotation, replacing context: Component-scan @propertysource, @value assigns values to variables, either directly or by using ${} to read information from the resource configuration file. @bean adds method return objects to the SpringIOC container

@Configuration
@ComponentScan({"cn.percent"})
@PropertySource({"classpath:jdbc.properties"})
public class SpringConfig {
    @Value("${jdbc.driver}")
    private String driverClassName;
    @Value(("${jdbc.url}"))
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value(("${jdbc.password}"))
    private String password;

    @Bean("dataSource")
    public DataSource createDataSource(a){
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName(driverClassName);
        druidDataSource.setUrl(url);
        druidDataSource.setUsername(username);
        druidDataSource.setPassword(password);
        returndruidDataSource; }}Copy the code

4.2 Spring IoC advanced features

4.2.1 lazy-init Lazy loading

The default behavior of the ApplicationContext container is to pre-instantiate all Singleton beans when starting the server. Pre-instantiation means that as part of the initialization process, the ApplicationContext instance will create and configure all Singleton beans.

<bean id="testBean" class="cn.percent.LazyBean" />The default setting for this bean is:<bean id="testBean" calss="cn.percent.LazyBean" lazy-init="false" />
Copy the code

Beans with lazy-init set to true will not be instantiated in advance when ApplicationContext is started, but when the bean is first requested from the container via getBean. If a bean1 set to load immediately refers to a lazy bean2, then Bean1 is instantiated when the container starts, and Bean2 is instantiated because it is referenced by Bean1, which also complies with the rule that delayed-loaded beans are instantiated only on the first invocation. You can also control delayed initialization at the container level by using the “default-lazy-init” attribute on elements. The configuration is as follows:

<beans default-lazy-init="true">
<! -- no beans will be eagerly pre-instantiated... -->
</beans>
Copy the code

If the scope property of a bean is scope=” potoType “, even if lazy-init=”false” is set, the container will not instantiate the bean at startup. Instead, it will instantiate the bean by calling the getBean method.

4.2.2 FactoryBean and the BeanFactory

The BeanFactory interface is the top-level interface of the container, defining the basic behavior of the container and a factory responsible for producing and managing beans, using subinterface types such as ApplicationContext. There are two types of beans in Spring: ordinary beans and factory beans. Factorybeans can generate instances of beans of a particular type (which are returned to us), which means we can customize the Bean creation process.

FactoryBean interface

// Allow us to customize the Bean creation process (complete the definition of complex beans)
public interface FactoryBean<T> {
    @Nullable
    // Returns the Bean instance created by FactoryBean. If isSingleton returns true, the instance will be placed in the Spring container's singleton cache pool Map
    T getObject(a) throws Exception;
    @Nullable
    // Returns the Bean type created by FactoryBeanClass<? > getObjectType();// Returns whether the scope is singleton
    default boolean isSingleton(a) {
        return true; }}Copy the code

Company Class

public class Company {
    private String name;
    private String address;
    private int scale;
    public String getName(a) {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAddress(a) {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public int getScale(a) {
        return scale;
    }
    public void setScale(int scale) {
        this.scale = scale;
    }
    @Override
    public String toString(a) {
    return "Company{" +
            "name='" + name + '\' ' +
            ", address='" + address + '\' ' +
            ", scale=" + scale +
            '} '; }}Copy the code

CompanyFactoryBean class

public class CompanyFactoryBean implements FactoryBean<Company> {
    private String companyInfo; // Company name, address, size
    public void setCompanyInfo(String companyInfo) {
        this.companyInfo = companyInfo;
    }
    @Override
    public Company getObject(a) throws Exception {
        // create a complex object Company
        Company company = new Company();
        String[] strings = companyInfo.split(",");
        company.setName(strings[0]);
        company.setAddress(strings[1]);
        company.setScale(Integer.parseInt(strings[2]));
        return company;
    }
    @Override
    publicClass<? > getObjectType() {return Company.class;
    }
    @Override
    public boolean isSingleton(a) {
        return true; }}Copy the code

The XML configuration

<bean id="companyBean" class="com.lagou.edu.factory.CompanyFactoryBean">
<property name="companyInfo" value="Percent, City Government Hang Lung,500"/>
</bean>
Copy the code

The test code

Object companyBean = applicationContext.getBean("companyBean");
System.out.println("bean:" + companyBean);
// The result is as follows
bean:Company{name='pull hook', address='Zhongguancun', scale=500}
Copy the code

If you want to get a FactoryBean, you need to prefix the ID with “&” &companyBean

Object companyBean = applicationContext.getBean("&companyBean");
System.out.println("bean:" + companyBean);
// The result is as follows
bean:com.lagou.edu.factory.CompanyFactoryBean@53f6fd09
Copy the code

The fifth part SpringIoC source code analysis

Spring source code is too complex, many functions have not been cleared logic, big god is big god, in the future to add comments.

Git address: https://gitee.com/FearlessYMF/spring-source-code-analysis.gitCopy the code

The sixth part Spring AOP application

1. The XML

  • The XML configuration

      
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd ">
    <! Base-pacjage specifies the package path to scan -->
    <context:component-scan base-package="cn.percent"></context:component-scan>
    <! -- Import third-party beans -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="JDBC: mysql: / / 172.16.3.219:3306 / ymf"></property>
        <property name="username" value="crawl"></property>
        <property name="password" value="crawl123"></property>
    </bean>


    <! Aop-related XML configuration -->
    <! -- Use the config tag to start the configuration, in the internal configuration aspect-->
    <bean id="logUtils" class="cn.percent.utils.LogUtils"></bean>
    <aop:config>
        <aop:aspect id="logAspect" ref="logUtils">
            <! -- Pointcut locks the method we are interested in using aspectJ expressions with fully qualified class names -->
            <aop:pointcut id="pt1" expression="execution(public void cn.percent.service.impl.TransferServiceImpl.transfer(String ,String ,int))"/>
            <! -- Location information -->
            <! -- AOP :before -->
<! -- <aop:before method="beforeMethod" pointcut-ref="pt1"></aop:before>-->
            <! Aop :after final notification, execute anyway -->
            <! -- AOP :after-returnning -->
            <! -- AOP :after-throwing -->
            <! -- Surround notification -->
            <aop:around method="arroundmethod" pointcut-ref="pt1"></aop:around>
        </aop:aspect>
    </aop:config>

</beans>
Copy the code
  • Perform class
package cn.percent.utils;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

public class LogUtils {
    public void beforeMethod(JoinPoint joinPoint){
        Object[] args = joinPoint.getArgs();

        System.out.println("Execute........ before business logic starts execution");
    }

    public void afterMehtod(a){
        System.out.println("The end of business logic is executed, regardless of the exception........");
    }

    public void exceptionMethod(a){
        System.out.println("Execute........ in case of exception");
    }


    public void successMethod(a){
        System.out.println("Perform........ when services are normal.");
    }
    // Wrap around the notification
    public Object arroundmethod(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("BeforeMethod in surround notification");
        Object result = null;
        try{
            result = proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
        } catch (Exception e) {
            System.out.println(ExceptionMethod in surround notice...);
        } finally {
            System.out.println("AfterMethod in surround notification...");
        }
        returnresult; }}Copy the code
  • Test functions
import cn.percent.service.TransferService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.sql.SQLException;

public class IoCTest {
    @Test
    public void testXmlAop(a) throws SQLException {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        TransferService transferService = applicationContext.getBean(TransferService.class);
        transferService.transfer("6029621011001"."6029621011000".2000); }}Copy the code

2. Annotation method

Add in the futureCopy the code

3. Source code analysis

Add in the futureCopy the code