Summary and review of Spring study notes (Crazy God said java)

Spring study notes

1.Spring

1.1 Introduction

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.0.RELEASE</version>
</dependency>

1.2. Composition

insert image description here

1.3 Advantages

● Non-intrusive design

Spring is a non-invasive framework that minimizes application code's dependence on the framework.
● Convenient decoupling and simplified development

Spring is a big factory, which can hand over the creation of all objects and the maintenance of dependencies to the Spring container management, which greatly reduces the coupling between components.
● Support AOP

Spring provides support for AOP, which allows centralized processing of some common tasks, such as security, transactions, logs, etc., thereby improving the reusability of programs.
● Supports declarative transaction processing

Transaction management can be completed only through configuration, without manual programming.
● Convenient program testing

Spring provides support for Junit4, which can easily test Spring programs through annotations.
● Reduce the difficulty of using Java EE API

Spring provides packaging for some APIs that are very difficult to use in Java EE development (such as: JDBC, JavaMail, etc.), which greatly reduces the difficulty of applying these APIs.

Two major features of Spirng

  • Inversion of Control (IOC), Aspect Oriented Programming (AOP)

2.IOC

1. UserDao interface

public interface UserDao {
    
    
    void getUser();
}

2. UserDaoImpl implementation class

public class UserDaoImpl implements UserDao {
    
    
    public void getUser() {
    
    
        System.out.println("默认获取用户数据");
    }
}

3. UserService business interface

public interface UserService {
    
    
    void getUser();
}

4. UserServiceImpl business implementation class

public class UserServiceImpl implements UserService {
    
    

    private UserDao userDao = new UserDaoImpl();

    public void getUser() {
    
    
        userDao.getUser();
    }
}

5. Test

public class MyTest {
    
    
    public static void main(String[] args) {
    
    

        //用户实际调用的是业务层,dao层他们不需要接触!
        UserService userService = new UserServiceImpl();
        userService.getUser();
    }
}

insert image description here
Here, set injection is used to change the initiative of the original program from the programmer to the user. Users can call whatever method they want, which greatly reduces the pressure on programmers to modify the code.

    private UserDao userDao;

    //利用set进行动态实现值的注入!
    public void setUserDao(UserDao userDao) {
    
    
        this.userDao = userDao;
    }

IOC essence

Inversion of Control (IOC) is a design idea, and DI dependency injection is a method to realize IOC. Without IOC, we use object-oriented programming. The creation of objects is controlled by the program, that is, our programmers. After using IOC, the initiative of object creation is reversed.
Through xml or annotations, to obtain the way to generate a specific object, the IOC container is used to implement inversion of control in Spring, and the implementation method is DI.

3.Hello World

Just build a maven project

Entity class

public class Hello {
    
    
    private String str;

    public String getStr() {
    
    
        return str;
    }

    public void setStr(String str) {
    
    
        this.str = str;
    }

    @Override
    public String toString() {
    
    
        return "Hello{" +
                "str='" + str + '\'' +
                '}';
    }
}

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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">


    <!--使用Spring来创建对象,在Spring这些都称为Bean
    类型 变量名 = new 类型();
    Hello hello = new Hello();

    id = 变量名
    class = new的对象
    property 相当于给对象中的属性设置一个值!
        -->
    <bean id="hello" class="com.kuang.pojo.Hello">
        <property name="str" value="Spring"/>
    </bean>
</beans>

last test

public class MyTest {
    
    
    public static void main(String[] args) {
    
    
        //获取Spring的上下文对象!
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        //我们的对象现在都在Spring中的管理了,我们需要使用,直接去里面取出来就可以!
        Hello hello = (Hello) context.getBean("hello");
        System.out.println(hello.toString());
    }
}
  • At this time, the object is created by the spring container, and its properties are also set by Spring.
    This process is Inversion of Control!

4. IOC creates objects

The moment the xml or other configuration files are loaded, the object has already been initialized.
By default, Spring creates objects using no-argument construction. Of course, we can also use parameter construction to create objects.
1. Subscript assignment

<!--第一种方式:下标赋值    -->
<bean id="user" class="com.kuang.pojo.User">
    <constructor-arg index="0" value="狂神说Java"/>
</bean>

2. Type (not recommended)

<!--第二种方式:通过类型的创建,不建议使用    -->
<bean id="user" class="com.kuang.pojo.User">
    <constructor-arg type="java.lang.String" value="lifa"/>
</bean>

3. Parameter name

<!--第三种方式:直接通过参数名来设置    -->
<bean id="user" class="com.kuang.pojo.User">
    <constructor-arg name="name" value="李发"/>
</bean>

5. Spring configuration

5.1 Aliases

If an alias is added, we can also use the alias to get this object.

    <alias name="user" alias="userNew"/>

In order to make the code more concise or reduce the amount of code.

5.2 Configuring beans

  • id: The unique identifier of the bean, which is equivalent to our object name

  • class: The fully qualified name corresponding to the bean object: package name + class name

  • name: It is also an alias, and name can take multiple aliases at the same time

    <bean id="userT" class="com.kuang.pojo.UserT" name="user2 u2,u3;u4">
        <property name="name" value="黑心白莲"/>
    </bean>

5.3import merged files

Generally used for team development, it can import and merge multiple configuration files into one.
Zhang San develops an xml, Li Si develops an xml, Wang Wu develops an xml, and finally creates an application.xml and uses import to import and merge into one xml.
I won’t write code here, just understand it.

6. Dependency Injection

6.1 Constructor injection

No parameter construction (spring default) and parameter construction, as mentioned earlier, will not be repeated here.

6.2 Set method injection ···Key points···

  • Dependency Injection: Set Injection
  • All attribute values ​​of the object are injected by the spring container!
    【Environment construction】
    1. Complex type
public class Address {
    
    
    private String address;

    public String getAddress() {
    
    
        return address;
    }

    public void setAddress(String address) {
    
    
        this.address = address;
    }
}

2. Test object

public class Student {
    
    

    private String name;
    private Address address;
    private String[] books;
    private List<String> hobbies;
    private Map<String,String> card;
    private Set<String> games;
    private String wife;
    private Properties info;
}

3、beans.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="student" class="com.kuang.pojo.Student">
        <!--第一种:普通值注入,value        -->
        <property name="name" value="黑心白莲"/>
    </bean>
</beans>

4. Test

public class MyTest {
    
    
    public static void main(String[] args) {
    
    
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        Student student = (Student) context.getBean("student");
        System.out.println(student.getName());
    }
}

5. Finally complete the information

    <bean id="address" class="com.kuang.pojo.Address">
        <property name="address" value="西安"/>
    </bean>

    <bean id="student" class="com.kuang.pojo.Student">
        <!--第一种:普通值注入,value        -->
        <property name="name" value="黑心白莲"/>

        <!--第二种:        -->
        <property name="address" ref="address"/>

        <!--数组        -->
        <property name="books">
            <array>
                <value>红楼梦</value>
                <value>西游记</value>
                <value>水浒传</value>
                <value>三国演义</value>
            </array>
        </property>

        <!--List        -->
        <property name="hobbies">
            <list>
                <value>打篮球</value>
                <value>看电影</value>
                <value>敲代码</value>
            </list>
        </property>

        <!--Map        -->
        <property name="card">
            <map>
                <entry key="身份证" value="123456789987456321"/>
                <entry key="银行卡" value="359419496419481649"/>
            </map>
        </property>

        <!--Set        -->
        <property name="games">
            <set>
                <value>LOL</value>
                <value>COC</value>
                <value>BOB</value>
            </set>
        </property>

        <!--NULL        -->
        <property name="wife">
            <null/>
        </property>

        <!--Properties        -->
        <property name="info">
            <props>
                <prop key="driver">20191029</prop>
                <prop key="url">102.0913.524.4585</prop>
                <prop key="user">黑心白莲</prop>
                <prop key="password">123456</prop>
            </props>
        </property>

    </bean>

The p and c namespaces can also be injected,
requiring import constraints

       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
<?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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--p命名空间注入,可以直接注入属性的值:property-->
    <bean id="user" class="com.kuang.pojo.User" p:name="黑心白莲" p:age="20"/>

    <!--c命名空间注入,通过构造器注入:constructor-args-->
    <bean id="user2" class="com.kuang.pojo.User" c:name="狂神" c:age="22"/>
</beans>

6.3 Scope of beans

  • singleton mode (default)
<bean id="user2" class="com.kuang.pojo.User" c:name="狂神" c:age="22" scope="singleton"/>
  • Prototype mode: Every time you get from the container, a new object will be generated!
<bean id="user2" class="com.kuang.pojo.User" c:name="狂神" c:age="22" scope="prototype"/>

7. Automatic assembly method (bean)

  • Spring will automatically look for it in the context and automatically assemble properties for the bean!
    1. Explicit configuration in xml;
    2. Explicit configuration in java;
    3. Implicit automatic assembly bean**

7.1 Testing

Create new modules, one person and two pets!

    <bean id="cat" class="com.kuang.pojo.Cat"/>
    <bean id="dog" class="com.kuang.pojo.Dog"/>

    <bean id="people" class="com.kuang.pojo.People">
        <property name="name" value="小白莲"/>
        <property name="cat" ref="cat"/>
        <property name="dog" ref="dog"/>
    </bean>

7.2 Nicknames

  • byName: It will automatically search in the container context, and the bean id corresponding to the value behind the set method of its own object!
        <bean id="people" class="com.kuang.pojo.People" autowire="byName">
            <property name="name" value="小白莲"/>
        </bean>

7.3 ByType

  • byType: It will automatically find beans of the same type as its own object properties in the container context!
        <bean id="people" class="com.kuang.pojo.People" autowire="byType">
            <property name="name" value="小白莲"/>
        </bean>

Notice:

  • When ByName, you need to ensure that the id of all beans is unique, and this bean needs to be consistent with the value of the set method of the automatically injected property!

  • When ByType, it is necessary to ensure that the class of all beans is unique, and this bean needs to be consistent with the type of the automatically injected property!

7.4 Implementation using annotations

Spring2.5 and above support annotations, and jdk1.5 and above support annotations!
1. Import constraints
2. Support for configuration annotations

<?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:context="http://www.springframework.org/schema/context"
       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">
		
		<!--开启注解的支持    -->
        <context:annotation-config/>
</beans>

@Autowired
can be used directly on the property! Can also be used on set methods!

test

public class People {
    
    
    //如果显式定义了Autowired的required属性为false,说明这个对象可以为null,否则不允许为空
    @Autowired(required = false)
    private Cat cat;
    @Autowired
    private Dog dog;
    private String name;
}

When automatic assembly cannot be completed, use @Qualifier(value = "xxx") to configure the use of @Autowired and specify a unique bean object to inject!

public class People {
    
    
    @Autowired
    @Qualifier(value = "cat111")
    private Cat cat;
    @Autowired
    @Qualifier(value = "dog222")
    private Dog dog;
    private String name;
}

@Resource

public class People {
    
    

    @Resource
    private Cat cat;

    @Resource
    private Dog dog;
}

The difference between @Resource and @Autowired:

  • Both are used for automatic assembly, and can be placed on the attribute field

  • @Autowired is implemented by byType, and this object must be required to exist! [commonly used]

  • @Resource is realized by byName by default, if the name cannot be found, it is realized by byType! If neither of them can be found, report an error! [commonly used]

  • The execution order is different: @Autowired is implemented by byType.

8. Annotation development

After Spring4, annotation development is basically used.
The use of annotations requires the import of constraints and the support of configuration annotations!

	<?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:context="http://www.springframework.org/schema/context"
	       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">
			
			<!--开启注解的支持    -->
	        <context:annotation-config/>
	</beans>

How bean properties are injected

//等价于<bean id="user" class="com.kuang.pojo.User"/>
//@Component 组件

@Component
public class User {
    
    

    //相当于  <property name="name" value="白莲"/>
    @Value("白莲")
    public String name;
}

derived annotation

  • @Component
  • dao 【@Repository】
  • service 【@Service】
  • controller [@Controller]
    has the same function, register a class in Spring, and assemble beans for
    automatic assembly
  • @Autowired: Autowire by type, name. If Autowired cannot uniquely automatically assemble the attribute, it needs to be configured through @Qualifier(value = "xxx").
  • The @Nullable field marks this annotation, indicating that this field can be null;
  • @Resource: Autowiring by name, type.
    The difference between xml and annotations
    xml is used to manage beans;
    annotations are only responsible for completing the injection of attributes;
    xml is more versatile and suitable for any occasion! Simple and convenient maintenance
    If the annotations take effect, you need to enable annotation support!
    <!--指定要扫描的包,这个包下的注解就会生效-->
    <context:component-scan base-package="com.kuang"/>
    <!--开启注解的支持    -->
    <context:annotation-config/>

9. Java way to configure Spring

From now on, don't use Spring's xml configuration, and leave it to java!

Entity class

//这里这个注解的意思,就是说明这个类被Spring接管了,注册到了容器中
@Component
public class User {
    
    
    private String name;

    public String getName() {
    
    
        return name;
    }

    @Value("黑心白莲") //属性注入值
    public void setName(String name) {
    
    
        this.name = name;
    }

    @Override
    public String toString() {
    
    
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}

configuration file

// 这个也会Spring容器托管,注册到容器中,因为它本来就是一个@Component
// @Configuration代表这是一个配置类,就和我们之前看的beans.xml
@Configuration
@ComponentScan("com.kuang.pojo")
@Import(KuangConfig2.class)
public class KuangConfig {
    
    

    // 注册一个bean,就相当于我们之前写的一个bean标签
    // 这个方法的名字,就相当于bean标签中id属性
    // 这个方法的返回值,就相当于bean标签中的class属性
    @Bean
    public User user(){
    
    
        return new User(); // 就是返回要注入到bean的对象!
    }
}

test

public class MyTest {
    
    
    public static void main(String[] args) {
    
    

        //如果完全使用了配置类方式去做,我们就只能通过 AnnotationConfig 上下文来获取容器,通过配置类的class对象加载!
        ApplicationContext context = new AnnotationConfigApplicationContext(KuangConfig.class);

        User user = context.getBean("user", User.class);
        System.out.println(user.getName());
    }
}

This method is often used in springboot!

10. Proxy mode

The proxy mode is the underlying principle of aop!
insert image description here

10.1 Static proxy

  • Abstract role: Generally, interfaces or abstract classes are used to solve
  • Real role: Proxied role
  • Acting role: Acting as a real character, after acting as a real character, we usually do some auxiliary operations
  • client: the person who accesses the proxy object!
    abstract role
//租房
public interface Rent {
    
    
    public void rent();
}

real role

//房东
public class Host implements Rent{
    
    
    public void rent() {
    
    
        System.out.println("房东出租房子!");
    }
}

agent role

public class Proxy implements Rent{
    
    
    private Host host;

    public Proxy() {
    
    
    }

    public Proxy(Host host) {
    
    
        this.host = host;
    }

    public void rent() {
    
    
        host.rent();
        seeHouse();
        sign();
        fee();
    }

    //看房
    public void seeHouse(){
    
    
        System.out.println("中介带着看房子!");
    }

    //签合同
    public void sign(){
    
    
        System.out.println("和中介签署租赁合同!");
    }

    //收费用
    public void fee(){
    
    
        System.out.println("中介收取费用!");
    }
}

Client Access Broker role

public class Client {
    
    
    public static void main(String[] args) {
    
    
        //房东要出租房子
        Host host = new Host();
//        host.rent();

        //代理,中介帮房东出租房子,并且代理角色一般会有一些附属操作!
        Proxy proxy = new Proxy(host);

        //不用面对房东,直接找中介租房即可!
        proxy.rent();
    }
}
  • Can make the operation of real characters more pure! No need to pay attention to some public business

  • The public role is handed over to the proxy role! The division of labor has been realized!

  • When the public business expands, it is convenient for centralized management!
    However, the amount of code will double, and the development efficiency will become lower!

10.2 Deepen understanding

abstract role

public interface UserService {
    
    
    public void add();
    public void delete();
    public void update();
    public void query();
}

real role

//真实角色
public class UserServiceImpl implements UserService{
    
    
    public void add() {
    
    
        System.out.println("增加了一个用户!");
    }

    public void delete() {
    
    
        System.out.println("删除了一个用户!");
    }

    public void update() {
    
    
        System.out.println("修改了一个用户!");
    }

    public void query() {
    
    
        System.out.println("查询了一个用户!");
    }
}

agent role

public class UserServiceProxy implements UserService{
    
    
    private UserServiceImpl userService;

    public void setUserService(UserServiceImpl userService) {
    
    
        this.userService = userService;
    }

    public void add() {
    
    
        log("add");
        userService.add();
    }

    public void delete() {
    
    
        log("delete");
        userService.delete();
    }

    public void update() {
    
    
        log("update");
        userService.update();
    }

    public void query() {
    
    
        log("query");
        userService.query();
    }

    public void log(String msg){
    
    
        System.out.println("[Debug] 使用了一个"+msg+"方法");
    }
}

Client Access Broker role

public class Client {
    
    
    public static void main(String[] args) {
    
    
        UserServiceImpl userService = new UserServiceImpl();

        UserServiceProxy proxy = new UserServiceProxy();
        proxy.setUserService(userService);

        proxy.delete();
    }
}

10.3 Dynamic proxy

  • Its proxy class is dynamically generated
  • It can be divided into two categories:
    1. Interface-based - JDK dynamic proxy
    2. Class-based: cglib
    3. Java bytecode implementation: javassist
    here to learn about the proxy class (Proxy) in advance; call handler (invocationHandler)
    abstract role
public interface Rent {
    
    
    public void rent();
}

**Real character

public class Host implements Rent{
    
    
    public void rent() {
    
    
        System.out.println("房东要出租房子!");
    }
}

ProxyInvocationHandler class

//我们会用这个类,自动生成代理类!
public class ProxyInvocationHandler implements InvocationHandler {
    
    
    //被代理的接口
    private Rent rent;

    public void setRent(Rent rent) {
    
    
        this.rent = rent;
    }

    //生成得到代理类
    public Object getProxy(){
    
    
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                rent.getClass().getInterfaces(),this);
    }

    //处理代理实例,并返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
        //动态代理的本质,就是使用反射机制实现!
        Object result = method.invoke(rent, args);
        seeHose();
        fee();
        return result;
    }

    public void seeHose(){
    
    
        System.out.println("中介带着看房子!");
    }

    public void fee(){
    
    
        System.out.println("中介收取费用!");
    }
}

test

public class Client {
    
    
    public static void main(String[] args) {
    
    
        //真实角色
        Host host = new Host();

        //代理角色:现在没有
        ProxyInvocationHandler pih = new ProxyInvocationHandler();

        //通过调用程序处理角色来处理我们要调用的接口对象!
        pih.setRent(host);
        Rent proxy = (Rent) pih.getProxy(); //这里的proxy就是动态生成的,我们并没有写
        proxy.rent();

    }
}

Put forward ProxyInvocationHandler as a tool class

//用这个类自动生成代理类!
public class ProxyInvocationHandler implements InvocationHandler {
    
    

    //被代理的接口
    private Object target;

    public void setTarget(Object target) {
    
    
        this.target = target;
    }

    //生成得到代理类
    public Object getProxy(){
    
    
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                target.getClass().getInterfaces(),this);
    }

    //处理代理实例,并返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
        log(method.getName());
        Object result = method.invoke(target, args);
        return result;
    }

    public void log(String msg){
    
    
        System.out.println("[Debug] 使用了一个"+msg+"方法");
    }
}

Benefits of dynamic proxies:

  • Can make the operation of real characters more pure! No need to pay attention to some public business
  • The public role is handed over to the proxy role! The division of labor has been realized!
  • When the public business expands, it is convenient for centralized management!
  • A dynamic proxy class proxies an interface, which generally corresponds to a type of business
  • A dynamic proxy class can proxy multiple classes, as long as the same interface is implemented!

11、AOP

11.1 Introduction to AOP

AOP (Aspect Oriented Programming) means: aspect-oriented programming, a technology that realizes unified maintenance of program functions through pre-compilation and runtime dynamic proxy.
insert image description here

11.2 The role of AOP in Spring

Provides declarative transactions; allows user-defined aspects

  • Cross-cutting concerns: Methods or functions that span multiple modules of an application. That is, the part that has nothing to do with our business logic, but we need to pay attention to, is the cross-cutting concern. Such as logging, security, caching, transactions, etc...
  • ASPECT: A special object where crosscutting concerns are modularized. That is, it is a class.
  • Advice: The work that the aspect must complete. That is, it is a method in the class.
  • Target: The object to be notified.
  • Proxy: An object created after a notification is applied to a target object.
  • PointCut: Definition of the "place" where aspect advice executes.
  • Connection point (JointPoint): The execution point that matches the pointcut.
    insert image description here
    Spring supports 5 types of advice:
    insert image description here
    aop is to add new functions without changing the original code.

11.3 Implementing AOP with Spring

To use AOP weaving, you need to import a dependency package!

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>

1. Use Spring's API interface [mainly Spring API interface implementation]
under the service package, define the UserService business interface and the UserServiceImpl implementation class

public interface UserService {
    
    
    public void add();
    public void delete();
    public void update();
    public void select();
}
public class UserServiceImpl implements UserService {
    
    
    public void add() {
    
    
        System.out.println("增加了一个用户!");
    }

    public void delete() {
    
    
        System.out.println("删除了一个用户!");
    }

    public void update() {
    
    
        System.out.println("更新了一个用户!");
    }

    public void select() {
    
    
        System.out.println("查询了一个用户!");
    }
}

Under the log package, define our enhancement class, a Log pre-enhancement and an AfterLog post-enhancement class

public class Log implements MethodBeforeAdvice {
    
    

    //method: 要执行的目标对象的方法
    //args:参数
    //target:目标对象
    public void before(Method method, Object[] agrs, Object target) throws Throwable {
    
    
        System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");
    }
}
public class AfterLog implements AfterReturningAdvice {
    
    

    //returnValue: 返回值
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
    
    
        System.out.println("执行了"+method.getName()+"方法,返回结果为:"+returnValue);
    }
}

Finally, register in the spring file, and implement aop cut-in implementation, pay attention to the import constraints, and configure the applicationContext.xml file

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--注册bean-->
    <bean id="userService" class="com.kuang.service.UserServiceImpl"/>
    <bean id="log" class="com.kuang.log.Log"/>
    <bean id="afterLog" class="com.kuang.log.AfterLog"/>

    <!--方式一:使用原生Spring API接口-->
    <!--配置aop:需要导入aop的约束-->
    <aop:config>
        <!--切入点:expression:表达式,execution(要执行的位置!* * * * *)-->
        <aop:pointcut id="pointcut" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/>

        <!--执行环绕增加!-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>

</beans>

test

public class MyTest {
    
    
    public static void main(String[] args) {
    
    
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        //动态代理代理的是接口:注意点
        UserService userService = (UserService) context.getBean("userService");

        userService.add();
//        userService.select();
    }
}

2. Customize the class to implement AOP [mainly aspect definition]
define your own DiyPointCut cut-in class under the diy package

public class DiyPointCut {
    
    
    public void before(){
    
    
        System.out.println("======方法执行前======");
    }

    public void after(){
    
    
        System.out.println("======方法执行后======");
    }
}

configuration file

    <!--方式二:自定义类-->
    <bean id="diy" class="com.kuang.diy.DiyPointCut"/>

    <aop:config>
        <!--自定义切面,ref 要引用的类-->
        <aop:aspect ref="diy">
            <!--切入点-->
            <aop:pointcut id="point" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/>
            <!--通知-->
            <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>

Third, use annotations to achieve!
AnnotationPointCut enhanced class defined under the diy package for annotation implementation

//声明式事务!
@Aspect //标注这个类是一个切面
public class AnnotationPointCut {
    
    

    @Before("execution(* com.kuang.service.UserServiceImpl.*(..))")
    public void before(){
    
    
        System.out.println("====方法执行前====");
    }

    @After("execution(* com.kuang.service.UserServiceImpl.*(..))")
    public void after(){
    
    
        System.out.println("====方法执行后====");
    }

    //在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点;
    @Around("execution(* com.kuang.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint jp) throws Throwable{
    
    
        System.out.println("环绕前");

        Signature signature = jp.getSignature();// 获得签名
        System.out.println("signature:"+signature);

        Object proceed = jp.proceed(); //执行方法

        System.out.println("环绕后");

        System.out.println(proceed);
    }

}

In the Spring configuration file, register the bean and add configurations that support annotations.

    <!--方式三:使用注解-->
    <bean id="annotationPointCut" class="com.kuang.diy.AnnotationPointCut"/>
    <!--开启注解支持! JDK(默认是 proxy-target-class="false")  cglib(proxy-target-class="true"-->
    <aop:aspectj-autoproxy/>

12. Declarative transactions

12.1 Reviewing Transactions

  • Treat a group of businesses as one business; either they all succeed or they all fail!

  • Transactions are very important in project development. When it comes to data consistency, you can't be sloppy!

  • Ensure completeness and consistency.
    Transaction ACID principles:

  • Atomicity

     事务是原子性操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么完全不起作用。
    
  • Consistency

     一旦所有事务动作完成,事务就要被提交。数据和资源处于一种满足业务规则的一致性状态中。
    
  • isolation

     可能多个事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。
    
  • Durability

     事务一旦完成,无论系统发生什么错误,结果都不会受到影响。通常情况下,事务的结果被写到持久化存储器中。
    

test:

Copy the above code into a new project
In the previous case, we added two methods to the userMapper interface, delete and add users;
copy the above code into a new project
In the previous case, we gave userMapper Added two methods to the interface, delete and add users;

//添加一个用户
int addUser(User user);

//根据id删除用户
int deleteUser(int id);

In the UserMapper file, we deliberately wrote the deletes wrong, test!

<insert id="addUser" parameterType="com.kuang.pojo.User">
insert into user (id,name,pwd) values (#{
    
    id},#{
    
    name},#{
    
    pwd})
</insert>

<delete id="deleteUser" parameterType="int">
deletes from user where id = #{
    
    id}
</delete>

Write the UserMapperImpl implementation class of the interface. In the implementation class, we will operate a wave

public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper {
    
    


    //增加一些操作
    public List<User> selectUser() {
    
    
        User user = new User(5, "小王", "185161");
        UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
        mapper.addUser(user);
        mapper.deleteUser(5);

        return mapper.selectUser();
    }
    
    //新增
    public int addUser(User user) {
    
    
        return getSqlSession().getMapper(UserMapper.class).addUser(user);
    }

    //删除
    public int deleteUser(int id) {
    
    
        return getSqlSession().getMapper(UserMapper.class).deleteUser(id);
    }
}

test

    @Test
    public void test(){
    
    
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        UserMapper userMapper = context.getBean("userMapper", UserMapper.class);

        for (User user : userMapper.selectUser()) {
    
    
            System.out.println(user);
        }
    }

Error: sql exception, delete is written wrong

Result: The database result shows that the insertion is successful!

There is no transaction management; we want them all to succeed to succeed, and if one fails, they all fail. We should need transactions!

In the past, we all needed to manually manage affairs by ourselves, which was very troublesome!

But Spring provides us with transaction management, we only need to configure;

12.2 Transaction Management in Spring

programmatic transaction management

  • Embed transaction management code into business methods to control transaction commit and rollback
  • Disadvantage: Additional transaction management code must be included in each transaction operation business logic
    Declarative transaction management
  • Generally easier to use than programmatic transactions.
  • Separate transaction management code from business methods, and implement transaction management in a declarative manner.
  • Take transaction management as a cross-cutting concern, and modularize it through the AOP method. Spring supports declarative transaction management through the Spring AOP framework.
    Use Spring to manage transactions, pay attention to the constraint import of the header file: tx
xmlns:tx="http://www.springframework.org/schema/tx"

http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">

JDBC transaction

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

After configuring the transaction manager, we need to configure transaction notifications

    <!--结合AOP实现事务的织入-->
    <!--配置事务通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--给那些方法配置事务-->
        <!--配置事务的传播特性: new -->
        <tx:attributes>
            <tx:method name="add" propagation="REQUIRED"/>
            <tx:method name="delete" propagation="REQUIRED"/>
            <tx:method name="update" propagation="REQUIRED"/>
            <tx:method name="query" read-only="true"/>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

Spring transaction propagation features:
transaction propagation behavior is how transactions propagate between these methods when multiple transaction methods call each other. Spring supports 7 transaction propagation behaviors:

  • propagation_requierd: If there is no transaction currently, create a new transaction. If there is already a transaction, join this transaction. This is the most common choice.
  • propagation_supports: supports the current transaction, if there is no current transaction, it will be executed in a non-transactional method.
  • propagation_mandatory: Use the current transaction, and throw an exception if there is no current transaction.
  • propagation_required_new: Create a new transaction, if there is a current transaction, suspend the current transaction.
  • propagation_not_supported: Perform operations in a non-transactional manner. If there is a current transaction, suspend the current transaction.
  • propagation_never: Perform the operation in a non-transactional manner, throwing an exception if the current transaction exists.
  • propagation_nested: Execute within a nested transaction if there is a current transaction. If there is no transaction currently, perform a similar operation to propagation_required.
    Spring's default transaction propagation behavior is PROPAGATION_REQUIRED, which is suitable for most situations.
    Configure AOP, import the header file of aop
    <!--配置事务切入-->
    <aop:config>
        <aop:pointcut id="txPointCut" expression="execution(* com.kuang.mapper.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
    </aop:config>

Delete the data you just inserted and test again!

    @Test
    public void test(){
    
    
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        UserMapper userMapper = context.getBean("userMapper", UserMapper.class);

        for (User user : userMapper.selectUser()) {
    
    
            System.out.println(user);
        }
    }

Why do you need transactions?

  • If you do not configure transactions, there may be inconsistencies in data submission;

  • If we don't configure declarative transactions in Spring, we need to manually configure transactions in code!

  • Transactions are very important in the development of the project, which involves data consistency and integrity issues, and should not be sloppy!
    Teacher Kuangshen's videos are really very suitable for the public to learn, and I have gained a lot in the process of watching and learning. Let us follow the video of Mr. Kuangshen and cheer together! Programmer!

Guess you like

Origin blog.csdn.net/lj20020302/article/details/129300548