avatar

Java Spring tutorial.

Java Spring tutorial.

bounty icon
$20
Single winner
Asked  9 months ago
Viewed  0 times

I need a enough-to-start-with java spring framework tutorial.

  • add comment
avatar

what is Spring ?

Spring is an open source framework. One of the main advantages of the framework is its layered architecture. The layered architecture allows users to choose which component to use while providing an integrated framework for J2EE application development. Spring uses basic JavaBeans to accomplish things that could only be done by EJB before. However, the use of Spring is not limited to server-side development. From the perspective of simplicity, testability, and loose coupling, any Java application can benefit from Spring. The core of Spring is inversion of control (IoC) and aspect-oriented-programming (AOP).

Spring features

①Convenient decoupling and simplify development

  Through the IoC container provided by Spring, we can hand over the dependencies between objects to Spring to control, avoiding excessive program coupling caused by hard coding. With Spring, users no longer need to write code for very low-level requirements such as single-instance mode classes and property file analysis, and can focus more on upper-level applications.

  ②AOP programming support

  The AOP function provided by Spring facilitates aspect-oriented programming, and many functions that are not easy to implement with traditional OOP can be easily handled by AOP.

  ③ Support for declarative transactions

  In Spring, we can get rid of the monotonous and boring transaction management code, and flexibly manage transactions in a declarative way to improve development efficiency and quality.

  ④convenient program testing

  You can use non-container-dependent programming for almost all testing work. In Spring, testing is no longer an expensive operation, but something that can be done at hand. For example: Spring supports Junit4, so you can easily test Spring programs through annotations.

  ⑤ Convenient integration of various excellent frameworks

  Spring does not exclude various excellent open source frameworks. On the contrary, Spring can reduce the difficulty of using various frameworks. Spring provides direct support for various excellent frameworks (such as Struts, Hibernate, Hessian, Quartz), etc.

  ⑥ Reduce the difficulty of using Java EE API

  Spring provides a thin encapsulation layer for many difficult-to-use Java EE APIs (such as JDBC, JavaMail, remote calls, etc.). Through Spring's simple encapsulation, the difficulty of using these Java EE APIs is greatly reduced.

  ⑦ Java source code is a classic learning example

  Spring's source code design is exquisite, clear in structure, and original ingenuity. It reflects the master's flexible use of Java design patterns and advanced knowledge of Java technology. The Spring framework source code is undoubtedly a best practice example of Java technology. If you want to quickly improve your Java technology level and application development level in a short period of time, learning and studying Spring source code will make you receive unexpected results.

Spring framework structure

Image for question

1. Core container: The core container provides the basic functions of the Spring framework (Spring Core). The main component of the core container is BeanFactory, which is the realization of the factory pattern. BeanFactory uses the Inversion of Control (IOC) model to separate the configuration and dependency specifications of the application from the actual application code.

  2. Spring context: Spring context is a configuration file that provides context information to the Spring framework. The Spring context includes enterprise services such as JNDI, EJB, e-mail, internationalization, verification and scheduling functions.

  3. Spring AOP: Through the configuration management feature, the Spring AOP module directly integrates the aspect-oriented programming function into the Spring framework. Therefore, any object managed by the Spring framework can easily support AOP. The Spring AOP module provides transaction management services for objects in Spring-based applications. By using Spring AOP, you can integrate declarative transaction management into your application without relying on EJB components.

  4. Spring DAO: The JDBCDAO abstraction layer provides a meaningful exception hierarchy, which can be used to manage exception handling and error messages thrown by different database vendors. The exception hierarchy simplifies error handling and greatly reduces the amount of exception code that needs to be written (such as opening and closing connections). Spring DAO's JDBC-oriented exceptions follow the general DAO exception hierarchy.

  5. Spring ORM: Spring framework inserts several ORM frameworks, thus providing ORM object relation tools, including JDO, Hibernate and iBatisSQL Map. All of these follow Spring's general transaction and DAO exception hierarchy.

  6. Spring Web module: The Web context module is built on top of the application context module to provide context for Web-based applications. Therefore, the Spring framework supports integration with Jakarta Struts. The web module also simplifies the work of processing multipart requests and binding request parameters to domain objects.

  7. Spring MVC framework: MVC framework is a full-featured MVC implementation for building Web applications. Through the strategy interface, the MVC framework becomes highly configurable. MVC accommodates a large number of view technologies, including JSP, Velocity, Tiles, iText, and POI. The model is composed of javabean and stored in the Map; the view is an interface, responsible for displaying the model; the controller represents the logic code and is the realization of the Controller. The features of the Spring framework can be used in any J2EE server, and most features are also applicable to unmanaged environments. The core point of Spring is to support reusable business and data access objects that are not bound to specific J2EE services. There is no doubt that such objects can be reused between different J2EE environments (Web or EJB), stand-alone applications, and test environments.

Spring framework features

Lightweight-Spring is lightweight in terms of size and overhead. The complete Spring framework can be published in a JAR file that is only 1MB in size. And the processing overhead required by Spring is also negligible. In addition, Spring is non-intrusive: Typically, objects in Spring applications do not depend on Spring's specific classes.

  Inversion of Control-Spring promotes low coupling through a technique called Inversion of Control (IoC). When IoC is applied, other objects that an object depends on will be passed in passively, instead of creating or finding dependent objects by itself. You can think of IoC as the opposite of JNDI—it's not that the object looks for dependencies from the container, but the container actively passes the dependencies to it when the object is initialized without waiting for the object's request.

  Aspect-oriented-Spring provides rich support for aspect-oriented programming, allowing cohesive development by separating application business logic and system-level services (such as auditing and transaction management). Application objects only implement what they are supposed to do-complete business logic-nothing more. They are not responsible (or even aware of) other system-level concerns, such as logging or transaction support.

  Container-Spring contains and manages the configuration and life cycle of application objects. In this sense, it is a container. You can configure how each of your beans is created-based on a configurable prototype, your bean You can create a single instance or generate a new instance every time you need it-and how they are related to each other. However, Spring should not be confused with traditional heavyweight EJB containers. They are often large and heavy and difficult to use.

  Framework-Spring can configure and combine simple components into complex applications. In Spring, application objects are combined declaratively, typically in an XML file. Spring also provides many basic functions (transaction management, persistence framework integration, etc.), leaving the development of application logic to you.

  MVC-The role of Spring is integration, but it is not limited to integration. The Spring framework can be regarded as an enterprise solution-level framework. The client sends the request, and the server controller (implemented by DispatcherServlet) completes the forwarding of the request. The controller calls a class HandlerMapping for mapping, which is used to map the request to the corresponding processor to process the request. HandlerMapping maps the request to the corresponding processor Controller (equivalent to Action). In Spring, if you write some processor components, generally implement the Controller interface, you can call some Service or DAO in the Controller to perform data operations. ModelAndView is used to store the slave DAO The data retrieved can also store some data of the response view. If you want to return the processing result to the user, a view component ViewResolver is also provided in the Spring framework. The component finds the corresponding view according to the indicator returned by the Controller, and returns the response to the user.

Spring advantages

Spring can effectively organize your middle-tier objects, regardless of whether you choose to use EJB. If you only use Struts or other frameworks that contain J2EE-specific APIs, you will find that Spring pays attention to the remaining problems. Spring can eliminate the excessive use of Singleton in many projects. According to my experience, this is a major problem, which reduces the testability and object-oriented characteristics of the system.

  Spring can eliminate the need to use various formats of attribute customization files, and can be configured in a consistent way throughout the application and project. Have you ever felt confused, a particular class has to look for psychedelic attribute keywords or system attributes, do you have to read Javadoc or even the source code? With Spring, you can easily see the JavaBean properties of a class.

  Spring can promote good programming habits through interfaces instead of classes, reducing programming costs to almost zero.

  Spring is designed to make applications created with it rely as little as possible on its APIs. Most business objects in Spring applications do not depend on Spring. So applications built with Spring are easy to unit test.

  Spring can make the use of EJB an implementation choice, rather than an inevitable choice for application architecture. You can choose to use POJOs or local EJBs to implement business interfaces without affecting the calling code.

  Spring helps you solve many problems without using EJB. Spring can provide an alternative to EJB, which is suitable for many web applications. For example, Spring can use AOP to provide declarative transactions without using an EJB container. If you only need to deal with a single database, you don't even need to implement JTA.

  Spring provides a consistent framework for data access, whether using JDBC or O/R mapping products (such as Hibernate).

  to sum up:

  1. Low intrusive design, extremely low code pollution

  2. Independent of various application servers, applications based on the Spring framework can truly realize the promise of Write Once and Run Anywhere

  3. Spring's DI mechanism reduces the complexity of business object replacement and improves the decoupling between components

  4. Spring's AOP support allows centralized management of some common tasks such as security, transactions, logs, etc., thereby providing better reuse

  5. Spring's ORM and DAO provide good integration with third-party persistence layer frameworks, and simplify the underlying database access

  6. Spring does not force applications to be completely dependent on Spring, developers are free to choose part or all of the Spring framework

IOC-Inversion of Control, that is, inversion of control. It is not a technology, but a design idea.

  The traditional method of creating objects is directly through the new keyword , while spring creates objects through the IOC container, which means that we give the control of creating objects to the IOC container. We can summarize IOC in one sentence:

  IOC allows programmers not to pay attention to how to create objects, but to focus on operations after object creation, and delegate the creation, initialization, and destruction of objects to the spring container.

Three ways to create objects in Spring containers

//This is the test object, we create the object through IOC
public class HelloIoc {

public void sayHello(){
System.out.println("Hello IOC");
}
}

The traditional method of creating objects: the new keyword

 @Test
public void testTradition(){
HelloIoc hello = new HelloIoc();
hello.sayHello();
}

The traditional method of creating objects: the new keyword

How to create it through the Spring container here?

  The first method: use the default construction method

  Create a new applicationContext.xml file in the src directory, this is the spring configuration file, add the following code:

<?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
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
The first way to create an object: using a parameterless constructor
id: unique identifier
class: the full class name of the class
-->
<bean id="helloIoc" class="com.my.ioc.HelloIoc" ></bean>
<!-- Alias attribute name: corresponds to the id attribute of the bean -->
<alias name="helloIoc" alias="helloIoc2"/>

</beans>

/**
* Spring container uses constructor to create objects
*/
@Test
public void testCreateObjectByConstrutor(){
//1, start the spring container
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
//2, take out the data from the spring container
HelloIoc IOC = (HelloIoc) context.getBean("helloIoc");
//3, call method through object
IOC.sayHello();

//Use the configuration file alias to create an object
HelloIoc IOC2 = (HelloIoc) context.getBean("helloIoc2");
IOC2.sayHello();
}

Manually add a construction method without parameters in HelloIoc.java, and then execute the above test code, you will find that the construction method will be called before the sayHello() method is executed.

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

<bean id="zhangsan" class="com.java.service.ZhangSan"></bean>
To
<bean id="lisi" class="com.java.service.Lisi"></bean>
To
<bean id="javaWork" class="com.java.service.JavaWork">
<property name="tester" ref="lisi"></property>
</bean>

</beans>

	public static void main(String[] args) {
ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml");
JavaWork javaWork=(JavaWork)ac.getBean("javaWork");
javaWork.doTest();
}

public class JavaWork {

private Tester tester;

public void setTester(Tester tester) {
this.tester = tester;
}

public void doTest(){
tester.test();
}
}

The second method: use the static factory method

  First create the static factory class HelloStaticFactory.java

public class HelloStaticFactory {
public HelloStaticFactory(){
System.out.println("HelloStaticFactory constructor");
}
//Static factory method
public static HelloIoc getInstances(){
return new HelloIoc();
}
}

Then configure the following in applicationContext.xml:

<!--
The second way to create objects: using static factory methods
factory-method: static method of obtaining object of static factory class
class: the full class name of the static factory class
-->
<bean id="helloStaticFactory" factory-method="getInstances" class="com.my.ioc.HelloStaticFactory"></bean>

/**
* The Spring container uses static factory methods to create objects
*/
@Test
public void createObjectStaticFactory(){
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
HelloIoc staticFactory =
(HelloIoc) context.getBean("helloStaticFactory");
staticFactory.sayHello();
}

The spring container is only responsible for calling the static factory method, and the internal implementation of this static factory method is done by the programmer

Using the instance factory method

  First create the instance factory class HelloInstanceFactory.java

public class HelloInstanceFactory {
public HelloInstanceFactory(){
System.out.println("Instance Factory Method Constructor");
}

//Using the instance factory method to create an object
public HelloIoc getInstance(){
HelloIoc instanceIoc = new HelloIoc();
return instanceIoc;
}
}

Then configure the following in applicationContext.xml:

<!--
The third way to create objects: use the instance factory method
factory-bean: Specify the beanID that contains the factory method in the current Spring
factory-method: factory method name
-->
<bean id="instanceFactory" class="com.my.ioc.HelloInstanceFactory"></bean>
<bean id="instance" factory-bean="instanceFactory" factory-method="getInstance"></bean>

/**
* The Spring container uses instance factory methods to create objects
*/
@Test
public void createObjectInstanceFactory(){
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
HelloIoc staticFactory =
(HelloIoc) context.getBean("instance");
staticFactory.sayHello();
}

When to create objects in the Spring container

By default, the object is created when the spring container is started

There is an attribute lazy-init="default/true/false" in the spring configuration file bean

    ① If lazy-init is "default/false", create an object when starting the spring container (default)

     ② If lazy-init is "true", the object must be created in context.getBean

 <bean id="helloIoc" lazy-init=“true” class="com.my.ioc.HelloIoc" ></bean>  

In the first case, you can check the correctness of the spring container configuration file when starting the spring container. If combined with tomcat, if the spring container cannot start normally, the entire tomcat cannot start normally. But the disadvantage of this is that some beans are placed in memory prematurely. If there is data, it will consume memory.

  Conversely, in the second case, memory consumption can be reduced, but it is not easy to find errors

Scope in spring bean: "singleton/prototype/request/session/global session"

1. The default scope value is singleton, that is, the generated object is singleton

  Configuration in the applicationContext.xml file:

<bean id="helloIoc" scope="singleton" class="com.my.ioc.HelloIoc" ></bean>

//The default object generated by spring container is singleton scope="singleton"
@Test
public void test_scope_single_CreateObject(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
HelloIoc hello1 = (HelloIoc) context.getBean("helloIoc");
HelloIoc hello2 = (HelloIoc) context.getBean("helloIoc");
System.out.println(hello1.equals(hello2)); //true
}

scope="prototype"

  Multi-case mode, and the object is not created when the spring container starts, but when the bean is obtained.

Summary: In the singleton mode, the spring container is started, and the object will be created; in the multi-case mode, the container will not be created when the container is started, and the object will be created when the bean is obtained

scope="request" Every HTTP request will create a new bean

scope="session" shares a Bean with the same HTTP Session

scope="global session" The same global Session shares a Bean, which is generally used in portlet application environments

scope="application" The same Application shares a Bean

Spring container life cycle

/**
* The life cycle of the Spring container
* @author hadoop
*
*/
public class SpringLifeCycle {
public SpringLifeCycle(){
System.out.println("SpringLifeCycle");
}
//Define the initialization method
public void init(){
System.out.println("init...");
}
//Define the destruction method
public void destroy(){
System.out.println("destroy...");
}

public void sayHello(){
System.out.println("say Hello...");
}
}

applicationContext.xml

<!-- Life cycle -->
<bean id="springLifeCycle" init-method="init" destroy-method="destroy" class="com.my.ioc.SpringLifeCycle"></bean>

public void testSpringLifeCycle(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
SpringLifeCycle hello = (SpringLifeCycle) context.getBean("springLifeCycle");

hello.sayHello();

//Destroy the spring container
ClassPathXmlApplicationContext classContext = (ClassPathXmlApplicationContext) context;
classContext.close();
}

Life cycle of spring container

     1. The spring container creates an object

  2. Execute the init method

  3. Call your own method

  4. Execute the destroy method when the spring container is closed

  Note: When the scope is "prototype", the destroy method will not be called when the close() method is called

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class T {

private ApplicationContext ac;

@Before
public void setUp() throws Exception {
ac=new ClassPathXmlApplicationContext("beans.xml");
}

@Test
public void test1() {
People people=(People)ac.getBean("people1");
People people2=(People)ac.getBean("people1");
System.out.println(people.getDog()==people2.getDog());

System.out.println(ac.getBean("dog")==ac.getBean("dog"));
}


}

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


<bean id="dog" class="com.java1234.entity.Dog" scope="prototype">
<property name="name" value="Jack"></property>
</bean>



<bean id="people1" class="com.java.entity.People">
<property name="id" value="1"></property>
<property name="name" value="张三"></property>
<property name="age" value="11"></property>
<lookup-method name="getDog" bean="dog"/>//方法动态注入
</bean>

</beans>


public abstract class People {

private int id;
private String name;
private int age;
private Dog dog;
public abstract Dog getDog();

public void setDog(Dog dog) {
this.dog = dog;
}
@Override
public String toString() {
return "People [id=" + id + ", name=" + name + ", age=" + age
+ ", dog=" + dog.getName() + "]";
}

}

Image for question

Method replacement

public class People {

private int id;
private String name;
private int age;
private Dog dog;

public Dog getDog() {
Dog dog=new Dog();
dog.setName("Jack");
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
}

public class People2 implements MethodReplacer {

@Override
public Object reimplement(Object arg0, Method arg1, Object[] arg2)
throws Throwable {
Dog dog=new Dog();
dog.setName("Tom");
return dog;
}

}

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


<bean id="people1" class="com.java.entity.People">
<property name="id" value="1"></property>
<property name="name" value="Joe"></property>
<property name="age" value="11"></property>
<replaced-method name="getDog" replacer="people2"></replaced-method>
</bean>

<bean id="people2" class="com.java.entity.People2"></bean>
</beans>

Image for question

DI dependency injection

Spring dynamically provides an object with other objects it needs. This is achieved through DI (Dependency Injection). For example, object A needs to operate a database. In the past, we always had to write code in A to obtain a Connection object. With spring, we only need to tell spring that a Connection is needed in A. As for how and when this Connection is constructed, A does not need to know. When the system is running, spring will create a Connection at an appropriate time, and then inject it into A like an injection, thus completing the control of the relationship between each object. A needs to rely on Connection to run normally, and this Connection is injected into A by spring, so the name of dependency injection comes from.

import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class Person {
private Long pid;
private String pname;
private Student students;
private List lists;
private Set sets;
private Map maps;
private Properties properties;
}

Assign values ​​in applicationContext.xml

<!--
property is used to describe the properties of a class
Basic types of packaging classes, String and other types that require values ​​are assigned with value
Reference type is assigned with ref
-->
<bean id="person" class="com.my.di.Person">
<property name="pid" value="1"></property>
<property name="pname" value="vae"></property>
<property name="students">
<ref bean="student"/>
</property>
<property name="students" ref="student">//Inject bean
<property name="students.name" value="jack">//cascade private Student students=new Student()

</property>

<property name="lists">
<list>
<value>1</value>
<ref bean="student"/>
<value>vae</value>
</list>
</property>

<property name="sets">
<set>
<value>1</value>
<ref bean="student"/>
<value>vae</value>
</set>
</property>

<property name="maps">
<map>
<entry key="m1" value="1"></entry>
<entry key="m2">
<ref bean="student"/>
</entry>
</map>
</property>

<property name="properties">
<props>
<prop key="p1">p1</prop>
<prop key="p2">p2</prop>
</props>
</property>

</bean>


<bean id="student" class="com.my.di.Student"></bean>

//Use the set method to assign a value to the object
@Test
public void testSet(){
//1, start the spring container
//2, take out the data from the spring container
//3, call method through object
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) context.getBean("person");
System.out.println(person.getPname());//vae
}

Use the constructor to assign values ​​to attributes

Add two construction methods in the entity class Person.java: with and without parameters

//Default constructor
public Person(){}
//Constructor with parameters
public Person(Long pid,Student students){
this.pid = pid;
this.students = students;
}

Assign values ​​in applicationContext.xml

<!-- Assign value according to the constructor -->
<!--
index represents the position of the parameter, starting from 0
type refers to the type of the parameter. When there are multiple constructors, you can use type to distinguish it. If you can determine which constructor is the function, you don’t need to write type
value Assign a value to the basic type
ref assigns a reference type
-->
<bean id="person_con" class="com.my.di.Person">
<constructor-arg index="0" type="java.lang.Long" value="1">
</constructor-arg>
<constructor-arg index="1" type="com.my.di.Student" ref="student_con"></constructor-arg>
</bean>
<bean id="student_con" class="com.my.di.Student"></bean>

//Use the constructor to assign a value to the object
@Test
public void testConstrutor(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) context.getBean("person_con");
System.out.println(person.getPid());//1
}

1. If there is no <constructor-arg> element in the bean in the spring configuration file, the default constructor is called

2. If there is a <constructor-arg> element in the bean in the spring configuration file, the element determines the only constructor

Type injection

public class People {

private int id;
private String name;
private int age;



public People() {
super();
// TODO Auto-generated constructor stub
}




public People(int id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
}


<bean id="people3" class="com.java.entity.People">
<constructor-arg type="int" value="2"></constructor-arg>
<constructor-arg type="String" value="Tom"></constructor-arg>
<constructor-arg type="int" value="22"></constructor-arg>
</bean>

OUTPUT

People [id=2,name=Tom,age=22]

Automatic assembly

byName automatically matches by name

<?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
http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="byName">


<bean id="dog" class="com.java.entity.Dog">
<property name="name" value="Jack"></property>
</bean>


<bean id="dog2" class="com.java.entity.Dog">
<property name="name" value="Joe"></property>
</bean>



<bean id="people1" class="com.java.entity.People">
<property name="id" value="1"></property>
<property name="name" value="Joe"></property>
<property name="age" value="11"></property>

</bean>

</beans>


public class People {

private int id;
private String name;
private int age;
private Dog dog;
}

OUTPUT

People [id=1,name=joe,age=11,dog=Jack]

byType: automatic matching by type

constructor: According to the type, automatic injection

<?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
http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="constructor">

<bean id="dog" class="com.java.entity.Dog">
<property name="name" value="Jack"></property>
</bean>



<bean id="people1" class="com.java.entity.People">
<property name="id" value="1"></property>
<property name="name" value="Joe"></property>
<property name="age" value="11"></property>

</bean>

</beans>


public class People {

private int id;
private String name;
private int age;
private Dog dog;

public People() {
super();
// TODO Auto-generated constructor stub
}

public People(Dog dog) {
super();
System.out.println("constructor");
this.dog = dog;
}
}

OUTPUT

constuctor

Peple [id=1,name=Joe,age=11,doc=Jack]

The relationship between beans

inherit

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

<bean id="dog" class="com.java.entity.Dog">
<property name="name" value="jack"></property>
</bean>

<bean id="abstractPeople" class="com.java.entity.People" abstract="true">
<property name="className" value="Senior"></property>
<property name="age" value="19"></property>
</bean>

<bean id="zhangsan" parent="abstractPeople" depends-on="autority">
<property name="id" value="1"></property>
<property name="name" value="Joe"></property>
</bean>

<bean id="lisi" parent="abstractPeople">
<property name="id" value="2"></property>
<property name="name" value="Tom"></property>
<property name="age" value="20"></property>
<property name="dog" ref="dog"></property>
</bean>


<bean id="autority" class="com.java.service.Authority"></bean>
</beans>

Output:

People [id=1,name=Joe,age=19,className=Senior]

People [id=2,name=Joe,age=20,className=Senior]

rely

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

<bean id="dog" class="com.java.entity.Dog">
<property name="name" value="jack"></property>
</bean>

<bean id="zhangsan" parent="abstractPeople" depends-on="autority">
<property name="id" value="1"></property>
<property name="name" value="Joe"></property>
</bean>

<bean id="lisi" parent="abstractPeople">
<property name="id" value="2"></property>
<property name="name" value="Tom"></property>
<property name="age" value="20"></property>
<property name="dog" ref="dog"></property>
</bean>


<bean id="autority" class="com.java.service.Authority"></bean>
</beans>

OUTPUT

People [id=1,name=Joe,age=19,className = senior]

People [id=2,name=Tom,age=20,className = senior]

Use annotations to let the Spring container generate Person objects for us

Use annotations

Introduce namespace in applicationContext.xml

Image for question

base-package: indicates the name of the package containing the annotation class

If you scan multiple packages, write multiple lines of the above code and change the contents of base-package!

@Component

   If the @Component annotation is added to a class, the following rules will be implemented

      If its value attribute is ""

            @Component

       public class Person {}

Equivalent to

      <bean id="person"class="..Person">

       If the value of its value attribute is not ""

      @Component("p")

      Public classPerson{}

Equivalent to

      <bean id="p"class="..Person">

Add the annotation @Component in the Person class

Image for question
public void testAnnotation(){
//1, start the spring container
//2, take out the data from the spring container
//3, call method through object
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) context.getBean("person");
System.out.println(person.getPname());
}

@Repository :dao layer

@Service:service layer

@Controller:web layer

Annotation @Resource

@Resource annotation, it can annotate class member variables, methods and constructors to complete the work of automatic assembly. Eliminate set and get methods through the use of @Resource.

  After @Resource annotation, judge whether the attribute of the annotation name is "" (name is not written)

  ①If the name attribute is not written, the value of the attribute name will be matched with the value of the ID in the spring configuration file bean (if not configured, it will also be matched with the annotation @Component), if the match is successful, the value will be assigned, if it matches Unsuccessful, it will match according to the spring configuration file class type, if the match is unsuccessful, an error will be reported

  ②If there is a name attribute, it will be matched according to the value of the name attribute and the ID in the spring bean. If the match is successful, the value will be assigned, and if the match is unsuccessful, an error will be reported

Without annotations:

<property name="students">
<ref bean="student"/>
</property>
<bean id="student" class="com.my.annotation_di.Student"></bean>

With annotations:

Image for question

Annotation @Autowired

The function is the same as the annotation @Resource, which can mark class member variables, methods and constructors to complete the work of automatic assembly. It's just that the annotation @Resource is assembled according to the name, while @Autowired is assembled according to the type.

When using @Autowired, first query the corresponding type of bean in the container

    If the query result is exactly one, the bean is assembled to the data specified by @Autowired

    If there is more than one result of the query, @Autowired will search by name.

    If the result of the query is empty, an exception will be thrown. When solving, use required=false

Create interface PersonDao

public interface PersonDao {

public void savePerson();

}

Create an interface implementation class PersonDaoImplOne

import org.springframework.stereotype.Component;

@Component("personDaoImplOne")
public class PersonDaoImplOne implements PersonDao{

@Override
public void savePerson() {
System.out.println("save Person One");

}

}

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("personService")
public class PersonService{
@Autowired
private PersonDao personDao;

public void savePerson() {
this.personDao.savePerson();
}

}

Note: Here we have added the annotation @Autowired to the private PesronDao personDao, it will first match according to the type, PersonDao is an interface, and its implementation class is PesronDaoImpOne, then the meaning here is:

  PersonDao personDao = new PersonDaoImpOne();

  So the question is, what if there are multiple implementation classes for PersonDao? We create the first implementation class PersonDaoImpTwo

The first method: change the name

Image for question

The second method: @Autowired and @Qualifier("name") are used together

Image for question

AOP (Aspect Oriented Programming), usually referred to as aspect-oriented programming. It uses a technique called "cross-cutting" to dissect the inside of the encapsulated object, and encapsulate those common behaviors that affect multiple classes into a reusable module, and name it "Aspect", which is the aspect . The so-called "aspects" are simply those logic or responsibilities that have nothing to do with the business, but are called by business modules, which are encapsulated, which is convenient to reduce the duplication of the system code, reduce the coupling between modules, and facilitate future operability And maintainability.

Static proxy

Both add and delete operations must open the transaction, and commit the transaction after the operation is completed.

public interface UserService {
//add user
public void addUser(User user);
//delete user
public void deleteUser(int uid);
}

Create the implementation class of UserService

public class UserServiceImpl implements UserService{
@Override
public void addUser(User user) {
System.out.println("Add User");
}
@Override
public void deleteUser(int uid) {
System.out.println("Delete User");
}
}

Create transaction class MyTransaction

public class MyTransaction {
//Open transaction
public void before(){
System.out.println("Open transaction");
}
//Submit transaction
public void after(){
System.out.println("Submit transaction");
}
}

Create proxy class ProxyUser.java

public class ProxyUser implements UserService{
//Real class
private UserService userService;
//Transaction class
private MyTransaction transaction;
//Use the constructor to instantiate
public ProxyUser(UserService userService,MyTransaction transaction){
this.userService = userService;
this.transaction = transaction;
}
@Override
public void addUser(User user) {
transaction.before();
userService.addUser(user);
transaction.after();
}
@Override
public void deleteUser(int uid) {
transaction.before();
userService.deleteUser(uid);
transaction.after();
}
}

@Test
public void testOne(){
MyTransaction transaction = new MyTransaction();
UserService userService = new UserServiceImpl();
//Generate a static proxy object
ProxyUser proxy = new ProxyUser(userService, transaction);
proxy.addUser(null);
proxy.deleteUser(0);
}

The business class UserServiceImpl only needs to focus on the business logic itself to ensure the reusability of the business, which is also the advantage of the proxy class

Disadvantages of writing like this:

① An interface of a proxy object only serves one type of object. If there are many proxy methods, it is necessary to proxy each method. Static proxy will not be competent when the program scale is slightly larger.

  ② If the interface adds a method, for example, UserService adds and modifies the updateUser() method, in addition to all implementation classes that need to implement this method, all proxy classes also need to implement this method. Increased the complexity of code maintenance.

Use JDK dynamic proxy

Do not manually generate proxy classes for dynamic proxy. We remove the ProxyUser.java class and add an ObjectInterceptor.java class

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import com.my.aop.one.MyTransaction;

public class ObjectInterceptor implements InvocationHandler{
//Target class
private Object target;
//Aspect class (here refers to transaction class)
private MyTransaction transaction;

//Assign via constructor
public ObjectInterceptor(Object target,MyTransaction transaction){
this.target = target;
this.transaction = transaction;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//Open transaction
this.transaction.before();
//Call the target class method
method.invoke(this.target, args);
//Submit transaction
this.transaction.after();
return null;
}

}

@Test
public void testOne(){
//Target class
Object target = new UserServiceImpl();
//Transaction class
MyTransaction transaction = new MyTransaction();
ObjectInterceptor proxyObject = new ObjectInterceptor(target, transaction);
/**
* The meaning of the three parameters:
* 1. The class loader of the target class
* 2. All the implemented interfaces of the target class
* 3. Interceptor
*/
UserService userService = (UserService) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), proxyObject);
userService.addUser(null);
}

Adding business methods to UserService later will automatically generate proxy objects for us without changing the code. And it is also possible to replace UserService with another class.

  That is to say, the proxy object can proxy multiple target classes and multiple target methods.

  Note: We are using JDK dynamic proxy here, and the requirement is that the interface must be implemented. Corresponding to another dynamic proxy implementation mode Cglib, it is not needed, we will not explain the implementation of cglib here.

AOP key terms

1.target: target class, the class that needs to be proxied. For example: UserService

  2. Joinpoint (connection point): The so-called connection point refers to those methods that may be intercepted. For example: all methods

  3. PointCut: A connection point that has been enhanced. For example: addUser()

  4. Advice notification/enhancement, enhanced code. For example: after, before

  5. Weaving: refers to the process of applying enhanced advice to the target object to create a new proxy object proxy.

  6.proxy proxy class: notification + entry point

  7. Aspect: It is a combination of pointcut and advice

  It can be understood according to the following picture:

Image for question

AOP notification types  

  Spring can be divided into 5 categories according to the position of the connection point of the notification advice in the target class method

  • Advance notice org.springframework.aop.MethodBeforeAdvice
  • Implement enhancements before the target method is executed, such as the before() method in the above example
  • Post notification org.springframework.aop.AfterReturningAdvice
  • Implement enhancements after the target method is executed, such as the after() method in the above example
  • Surround notification org.aopalliance.intercept.MethodInterceptor
  • Implement enhancements before and after target method execution
  • Exception thrown notification org.springframework.aop.ThrowsAdvice
  • Implement enhancements after the method throws an exception
  • Introduction notice org.springframework.aop.IntroductionInterceptor

Add some new methods and properties to the target class

We only need to configure the following in Spring's configuration file applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--1, create target class -->
<bean id="userService" class="com.my.aop.UserServiceImpl"></bean>
<!--2, create an aspect class (notice) -->
<bean id="transaction" class="com.my.aop.one.MyTransaction"></bean>

<!--3, aop programming
3.1 Import namespace
3.2 Use <aop:config> to configure
proxy-target-class="true" uses cglib proxy when declared
If not declared, Spring will automatically choose cglib proxy or JDK dynamic proxy
<aop:pointcut> Entry point, get specific methods from the target
<aop:advisor> Special aspect, only one notification and one entry point
advice-ref advice reference
pointcut-ref pointcut reference
3.3 Pointcut expression
execution(* com.my.aop.*.*(..))
Selection method Any return value Any package Class name Any method name Any parameter

-->
<aop:config>
<!-- Pointcut expression -->
<aop:pointcut expression="execution(* com.my.aop.*.*(..))" id="myPointCut"/>
<aop:aspect ref="transaction">
<!-- Configure the pre-notification, note that the value of method should be the same as the name of the class method of the corresponding aspect -->
<aop:before method="before" pointcut-ref="myPointCut"></aop:before>
<aop:after-returning method="after" pointcut-ref="myPointCut"/>
</aop:aspect>
</aop:config>
</beans>

@Test
public void testAop(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService useService = (UserService) context.getBean("userService");
useService.addUser(null);
}

①The entry point expression, a complete method is expressed as follows:

execution (modifiers-pattern? ref-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
Class modifier; Return value; package of method; Method name; The exception

Then according to the above comparison, we can understand very well:

execution(* com.my.aop.*.*(..))
Select method; Any return value; package; any Class name; Any method name; Any parameter;

Then it means that the return value is arbitrary, the package name is any method name in any class name under com.ys.aop, and the parameters are arbitrary.

What if the pointcut expression has multiple different directories?

<aop:pointcut expression="execution(* com.my.*Service1.*(..)) ||
execution(* com.my.*Service2.*(..))" id="myPointCut"/>

It means to match any method of the class ending with Service1 or Service2 under the com.my package.

AOP pointcut expressions support multiple forms of definition rules:

1. Execution: execution of matching method (commonly used)
execution(public *.*(..))
2.within: match the method in the package or sub-package
within(com.my.aop..*)
3.this: match the method in the proxy object that implements the interface
this(com.my.aop.user.UserDAO)
4.target: Match the method in the target object that implements the interface
target(com.my.aop.user.UserDAO)
5.args: The method of matching parameter format in accordance with the standard
args(int,int)
6.bean(id) methods to the specified bean
bean('userServiceId')

② The specific loading steps of springAOP:

  1. When the spring container starts, the spring configuration file is loaded

  2. Create objects for all beans in the configuration file

  3. The spring container will parse the configuration of aop:config

Analyze the pointcut expression and use the pointcut expression to match the bean included in the spring container

If the match is successful, a proxy object will be created for the bean, and the method of the proxy object = target method + notification

If the match is unsuccessful, no proxy object will be created

  4. When the client uses context.getBean() to obtain an object, if the object has a proxy object, the proxy object is returned; if not, the target object is returned

  Note: If the target class does not implement the interface, the spring container will use cglib to generate proxy objects, if the interface is implemented, it will use jdk.

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

public class StudentServiceAspect {

public void doBefore(JoinPoint jp){
System.out.println("Class name:"+jp.getTarget().getClass().getName());
System.out.println("Method name:"+jp.getSignature().getName());
System.out.println("Start adding student:"+jp.getArgs()[0]);
}
To
public void doAfter(JoinPoint jp){
System.out.println("Class name:"+jp.getTarget().getClass().getName());
System.out.println("Method name:"+jp.getSignature().getName());
System.out.println("Student addition completed:"+jp.getArgs()[0]);
}
To
public Object doAround(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("Before adding student");
Object retVal=pjp.proceed();
System.out.println(retVal);
System.out.println("After adding student");
return retVal;
}
To
public void doAfterReturning(JoinPoint jp){
System.out.println("Return notification");
}
To
public void doAfterThrowing(JoinPoint jp,Throwable ex){
System.out.println("Exception Notification");
System.out.println("Exception information:"+ex.getMessage());
}
}

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">

<bean id="studentServiceAspect" class="com.java.advice.StudentServiceAspect"></bean>

<bean id="studentService" class="com.java.service.impl.StudentServiceImpl"></bean>

<aop:config>
<aop:aspect id="studentServiceAspect" ref="studentServiceAspect">
<aop:pointcut expression="execution(* com.java.service.*.*(..))" id="businessService"/>
<aop:before method="doBefore" pointcut-ref="businessService"/>
<aop:after method="doAfter" pointcut-ref="businessService"/>
<aop:around method="doAround" pointcut-ref="businessService"/>
<aop:after-returning method="doAfterReturning" pointcut-ref="businessService"/>
<aop:after-throwing method="doAfterThrowing" pointcut-ref="businessService" throwing="ex"/>
</aop:aspect>
</aop:config>
</beans>

public class StudentServiceImpl implements StudentService{

@Override
public void addStudent(String name) {
// System.out.println("Start adding student"+name);
System.out.println("Add student"+name);
System.out.println(1/0);
// System.out.println("Complete the addition of students"+name+"");
}

}

OUTPUT

Method name:addStudent

Start adding student

Add student Joe

Before adding student

Add student Joe

Return notification

null

After adding student

AspectJ is an aspect-oriented framework that extends the Java language.

Aspect notification type defines the type name and method format. The types are as follows:

before: pre-notification (application: various verification)
Execute before the method is executed, if the notification throws an exception, prevent the method from running
afterReturning: Post notification (application: regular data processing)
The method is executed after the normal return, if an exception is thrown in the method, the notification cannot be executed
It must be executed after the method is executed, so the return value of the method can be obtained.
around: around notifications (application: very powerful, can do anything)
The method is executed before and after execution, which can prevent the execution of the method
The target method must be executed manually
afterThrowing: throw exception notification (application: wrap exception information)
The method is executed after throwing an exception, if the method does not throw an exception, it cannot be executed
after: final notice (application: cleaning up the scene)
Execute after the method is executed, regardless of whether there is an exception in the method

The most important thing here is the around notice, which can replace any notice above.

The meaning expressed in the program is as follows:

try{
//before
//Manually execute the target method
//afterRetruning
} catch(){
//afterThrowing
} finally{
//after
}

AOP specific examples

public interface UserService {
public void addUser();
public void deleteUser();
}

Create an implementation class

public class UserServiceImpl implements UserService{
@Override
public void addUser() {
System.out.println("Add User");
}
@Override
public void deleteUser() {
System.out.println("Delete User");
}
}

Create aspect classes (including various notifications)

import org.aspectj.lang.JoinPoint;


public class MyAspect {
/**
* JoinPoint can get some basic information about the target method
* @param joinPoint
*/
public void myBefore(JoinPoint joinPoint){
System.out.println("Pre-notification: "+ joinPoint.getSignature().getName());
}

public void myAfterReturning(JoinPoint joinPoint,Object ret){
System.out.println("Post notification: "+ joinPoint.getSignature().getName() +", -->" + ret);
}

public void myAfter(){
System.out.println("Final Notice");
}

}

Create spring configuration file applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--1, create target class -->
<bean id="userService" class="com.my.aop.UserServiceImpl"></bean>
<!--2, create an aspect class (notice) -->
<bean id="myAspect" class="com.my.aop.MyAspect"></bean>

<!--3, aop programming
3.1 Import namespace
3.2 Use <aop:config> to configure
proxy-target-class="true" uses cglib proxy when declared
If not declared, Spring will automatically choose cglib proxy or JDK dynamic proxy
<aop:pointcut> Entry point, get specific methods from the target
<aop:advisor> Special aspect, only one notification and one entry point
advice-ref advice reference
pointcut-ref pointcut reference
3.3 Pointcut expression
execution(* com.my.aop.*.*(..))
Selection method Any return value Any package Class name Any method name Any parameter

-->
<aop:config>
<aop:aspect ref="myAspect">
<!-- Pointcut expression -->
<aop:pointcut expression="execution(* com.my.aop.*.*(..))" id="myPointCut"/>
<!-- 3.1 Pre-notification
<aop:before method="" pointcut="" pointcut-ref=""/>
method: notification, and method name
pointcut: Pointcut expression, this expression can only be used in the current notification.
pointcut-ref: Pointcut reference, which can share pointcuts with other notifications.
Notification method format: public void myBefore(JoinPoint joinPoint){
Parameter 1: org.aspectj.lang.JoinPoint is used to describe the connection point (target method), obtain the target method name, etc.
-->
<aop:before method="myBefore" pointcut-ref="myPointCut"/>


<!-- 3.2 Post notification, execute after the target method, get the return value
<aop:after-returning method="" pointcut-ref="" returning=""/>
The name of the second parameter of the returning notification method
Notification method format: public void myAfterReturning(JoinPoint joinPoint,Object ret){
Parameter 1: Connection point description
Parameter 2: Type Object, parameter name returning="ret" configured
-->
<aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="ret" />

<!-- 3.3 Final notice -->
<aop:after method="myAfter" pointcut-ref="myPointCut"/>

</aop:aspect>
</aop:config>
</beans>

@Test
public void testAop(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService useService = (UserService) context.getBean("userService");
useService.addUser();
}

Test exception notification

public void addUser() {
int i = 1/0;//Obviously it will throw that the divisor cannot be 0
System.out.println("Add User");
}

Noodles

public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
System.out.println("Throwing exception notification: "+ e.getMessage());
}

<!-- 3.4 Throw an exception
<aop:after-throwing method="" pointcut-ref="" throwing=""/>
throwing: the name of the second parameter of the notification method
Notification method format: public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
Parameter 1: Connection point description object
Parameter 2: Get exception information, type Throwable, parameter name is configured by throwing="e"
-->
<aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e"/>

@Test
public void testAop(){
String str = "com/my/execption/applicationContext.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(str);
UserService useService = (UserService) context.getBean("userService");
useService.addUser();
}

Test surround notification

public class MyAspect {

public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("Pre-notification");
//Manually execute the target method
Object obj = joinPoint.proceed();

System.out.println("Post notification");
return obj;
}

}

The applicationContext.xml configuration is as follows:

Through xml configuration.

<!-- Surround notification
<aop:around method="" pointcut-ref=""/>
Notification method format: public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
Return value type: Object
Method name: any
Parameters: org.aspectj.lang.ProceedingJoinPoint
Throw an exception
Execution target method: Object obj = joinPoint.proceed();
-->
<aop:around method="myAround" pointcut-ref="myPointCut"/>

@Test
public void testAop(){
String str = "com/my/around/applicationContext.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(str);
UserService useService = (UserService) context.getBean("userService");
useService.addUser();
}

Annotation to achieve AOP

 @Aspect declares the aspect, modifies the aspect class, and gets notified.

  Notice

    @Before

    @AfterReturning after

    @Around surround

    @AfterThrowing throws an exception

    @After finally

  Entry point

    @PointCut, after modifying the method private void xxx(){}, get the pointcut reference through the "method name"

Import the corresponding namespace in 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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">

</beans>

Annotation configuration bean

 xml configuration:

<!--1, create a target class -->
<bean id="userService" class="com.my.aop.UserServiceImpl"></bean>
<!--2, create an aspect class (notice) -->
<bean id="myAspect" class="com.my.aop.MyAspect"></bean>

Image for question

Configure scan annotation recognition

Add the following configuration in the applicationContext.xml file:

<!-- Configure scan annotation class
base-package: indicates the package name containing the annotation class.
If you scan multiple packages, write the following code in multiple lines and change the content in base-package!
-->
<context:component-scan base-package="com.my.aop"></context:component-scan>

Add @Aspect annotation to the aspect class as follows:

Tell Spring which is the aspect class

Image for question

How to make Spring recognize the AOP annotations we configured

  We add the following configuration to the applicationContext.xml file:

<!--2, make sure the aop annotation takes effect -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

Annotation configuration pre-notification

  We first look at the xml configuration pre-notification as follows:

<!-- Pointcut expression -->
<aop:pointcut expression="execution(* com.my.aop.*.*(..))" id="myPointCut"/>
<!-- 3.1 Pre-notification
<aop:before method="" pointcut="" pointcut-ref=""/>
method: notification, and method name
pointcut: Pointcut expression, this expression can only be used in the current notification.
pointcut-ref: Pointcut reference, which can share pointcuts with other notifications.
Notification method format: public void myBefore(JoinPoint joinPoint){
Parameter 1: org.aspectj.lang.JoinPoint is used to describe the connection point (target method), obtain the target method name, etc.
-->
<aop:before method="myBefore" pointcut-ref="myPointCut"/>

Then the way of annotation is as follows:

Image for question

Annotation configuration post notification

xml configuration post notification:

<!-- 3.2 Post notification, execute after the target method, get the return value
<aop:after-returning method="" pointcut-ref="" returning=""/>
The name of the second parameter of the returning notification method
Notification method format: public void myAfterReturning(JoinPoint joinPoint,Object ret){
Parameter 1: Connection point description
Parameter 2: Type Object, parameter name returning="ret" configured
-->
<aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="ret" />

Note that the post notification has a returning="ret" configuration, which is used to obtain the return value of the target method.

Transaction generally refers to something to be done or done. In computer terms, it refers to a program execution unit (unit) that accesses and may update various data items in the database.

  Here we explain with an example of withdrawing money: For example, if you go to an ATM to withdraw 1,000 dollars, there are roughly two steps: the first step is to enter the password amount, and the bank card deducts 1,000 dollars; the second step is 1,000 dollars from the ATM . Both of these steps must be executed or neither. If the bank card deducts 1,000 dollars but the ATM fails to pay, you will lose 1,000 dollars; if the bank card deduction fails but the ATM pays 1,000 dollars, then the bank will lose 1,000 dollars.

  How to ensure that one of these two steps will not be abnormal while the other is executed successfully? Affairs is used to solve such problems. A transaction is a series of actions. They are integrated together to be a complete unit of work. These actions must all be completed. If one fails, the transaction will roll back to the initial state, as if nothing happened. . In enterprise-level application development, transaction management is an essential technology to ensure data integrity and consistency.

Four characteristics of transactions (ACID)

  ① Atomicity: A transaction is an atomic operation and consists of a series of actions. The atomicity of the transaction ensures that the actions are either all completed or completely ineffective.

  ② Consistency: Once the transaction is completed (regardless of success or failure), the system must ensure that the business modeled by it is in a consistent state, rather than partially completed and partially failed. Data in reality should not be destroyed.

  ③ Isolation (Isolation): There may be many transactions that process the same data at the same time, so each transaction should be isolated from other transactions to prevent data corruption.

  ④ Durability: Once the transaction is completed, no matter what system error occurs, its result should not be affected, so that it can recover from any system crash. Normally, the result of the transaction is written to persistent storage.

PlatformTransactionManager transaction manager

 The interface of Spring transaction manager is org.springframework.transaction.PlatformTransactionManager. Spring does not directly manage transactions. Through this interface, Spring provides corresponding transaction managers for various platforms such as JDBC, Hibernate, etc. Responsibilities are delegated to the affairs of the relevant platform framework provided by persistence mechanisms such as Hibernate or JTA.

That is to say, Spring transaction management provides a consistent programming model for different transaction APIs, and the specific transaction management mechanism is implemented by each platform.

AccountDao interface:

public interface AccountDao {
/**
* money transfer
* @param outer remitter
* @param money remittance amount
*/
public void out(String outer,int money);

/**
* Collection
* @param inner payee
* @param money collection amount
*/
public void in(String inner,int money);

import org.springframework.jdbc.core.support.JdbcDaoSupport;

import com.my.dao.AccountDao;

public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {

/**
* Decrease the account amount according to the user name
*/
@Override
public void out(String outer, int money) {
this.getJdbcTemplate().update("update account set money = money-? where username = ?",money,outer);
}

/**
* Increase account amount based on user name
*/
@Override
public void in(String inner, int money) {
this.getJdbcTemplate().update("update account set money = money +? where username = ?",money,inner);
}

}

public interface AccountService {

/**
* Transfer
* @param outer remitter
* @param inner payee
* @param money transaction amount
*/
public void transfer(String outer,String inner,int money);

}

public class AccountServiceImpl implements AccountService{

private AccountDao accountDao;

public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public void transfer(String outer, String inner, int money) {
accountDao.out(outer, money);
accountDao.in(inner, money);
}

}

<?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"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>

<bean id="accountDao" class="com.my.dao.impl.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>

<bean id="accountService" class="com.my.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>
</beans>

public class TransactionTest {

@Test
public void testNoTransaction(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
AccountService account = (AccountService) context.getBean("accountService");
//Tom transfer 1000 to Marry
account.transfer("Tom", "Marry", 1000);
}

}

Programmatic transaction processing : The so-called programmatic transaction refers to the realization of the transaction by coding, allowing users to precisely define the boundary of the transaction in the code. That is similar to JDBC programming to achieve transaction management. Management uses TransactionTemplate or directly uses the underlying PlatformTransactionManager. For programmatic transaction management, Spring recommends using TransactionTemplate.

Declarative transaction processing : Management is based on AOP. Its essence is to intercept before and after the method, then create or add a transaction before the target method starts, and submit or roll back the transaction according to the execution after the target method is executed. The biggest advantage of declarative transactions is that they do not need to be managed by programming, so there is no need to dope transaction management code in the business logic code. You only need to make relevant transaction rule declarations in the configuration file (or through @Transactional Annotation), you can apply transaction rules to business logic.

  Simply put, programmatic transactions invade the business code, but provide more detailed transaction management; and declarative transactions, based on AOP, can not only play a role in transaction management, but also do not affect the specific implementation of the business code.

Programmatic transaction processing to realize transfer (TransactionTemplate)

We inject the TransactionTemplate template in the Service layer. Because the template is used to manage transactions, the template needs to be injected into the transaction manager DataSourceTransactionManager. The transaction manager is still managed by the underlying JDBC after all, so we need to inject the DataSource into the transaction manager. These steps are as follows:

AccountServiceImpl interface:

import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import com.my.dao.AccountDao;
import com.my.service.AccountService;

public class AccountServiceImpl implements AccountService{

private AccountDao accountDao;
private TransactionTemplate transactionTemplate;

public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public void transfer(final String outer,final String inner,final int money) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus arg0) {
accountDao.out(outer, money);
//int i = 1/0;
accountDao.in(inner, money);
}
});
}

}

Spring global configuration file applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>

<bean id="accountDao" class="com.my.dao.impl.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>

<bean id="accountService" class="com.my.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
<property name="transactionTemplate" ref="transactionTemplate"></property>
</bean>

<!-- Create template -->
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="txManager"></property>
</bean>

<!-- Configure the transaction manager, the manager needs transactions, the transaction is obtained from Connection, and the connection is obtained from the connection pool DataSource -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>

The underlying PlatformTransactionManager for transaction management

//Define a TransactionManager of a certain framework platform, such as JDBC, Hibernate
DataSourceTransactionManager dataSourceTransactionManager =
new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(this.getJdbcTemplate().getDataSource()); // Set the data source

DefaultTransactionDefinition transDef = new DefaultTransactionDefinition(); // Define transaction attributes
transDef.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED); // Set the propagation behavior property
TransactionStatus status = dataSourceTransactionManager.getTransaction(transDef); // Get transaction status
try {
// Database operation
accountDao.out(outer, money);
int i = 1/0;
accountDao.in(inner, money);

dataSourceTransactionManager.commit(status);// Submit
} catch (Exception e) {
dataSourceTransactionManager.rollback(status);// rollback
}

Declarative transaction processing to realize transfer (based on AOP xml configuration)

The Dao layer and the Service layer remain unchanged from the transaction we started with to realize transfers. Mainly the applicationContext.xml file has changed.

  We configure aop to automatically generate a proxy in the applicationContext.xml file for transaction management:

  ①configuration manager

  ②configuration transaction details

  ③configure aop

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

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>

<bean id="accountDao" class="com.my.dao.impl.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>

<bean id="accountService" class="com.my.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>

<!-- 1 Transaction Manager -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>

<!-- 2 Transaction details (transaction notification), based on aop screening, for example, determine what kind of transaction to use for the three ABCs. For example: AC read-write, B read-only, etc.
<tx:attributes> is used to configure transaction details (attributes)
<tx:method name=""/> Details specific configuration
propagation behavior, REQUIRED: must; REQUIRES_NEW: must be new
isolation level
-->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="transfer" propagation="REQUIRED" isolation="DEFAULT"/>
<tx:method name="*"/>//All methods
</tx:attributes>
</tx:advice>

<!-- 3 AOP programming, using the entry point expression to determine the enhanced connector from the target class method to obtain the entry point -->
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.my.service..*.*(..))"/>//Configure thing notification
<aop:pointcut expression="execution(* com.my.service..*.*(..))" id="serviceMethod">//configuration pointcut
</aop:config>
</beans>

1. Propagation behavior: When a transaction method is called by another transaction method, you must specify how the transaction should be propagated.

  Spring defines the following seven propagation behaviors. Here is how to propagate transactions between A business and B business as an example:

  ①PROPAGATION_REQUIRED: required, required. By default, if A has a transaction, B will use that transaction; if A has no transaction, B will create a new transaction.

  ②PROPAGATION_SUPPORTS: supports, support. If A has a transaction, B will use that transaction; if A has no transaction, B will execute as a non-transactional.

  ③PROPAGATION_MANDATORY: mandatory, mandatory. If A has a transaction, B will use that transaction; if A has no transaction, B will throw an exception.

  ④PROPAGATION_REQUIRES_NEW: requires_new, must be new. If A has a transaction, suspend A’s transaction and B creates a new transaction; if A has no transaction, B creates a new transaction.

  ⑤PROPAGATION_NOT_SUPPORTED: not_supported, not supported. If A has a transaction, suspend A's transaction and B will be executed as a non-transactional; if A has no transaction, B will be executed as a non-transactional.

  ⑥PROPAGATION_NEVER: never, never. If A has a transaction, B will throw an exception; if A has no transaction, B will execute as a non-transactional.

  ⑦PROPAGATION_NESTED : nested, nested. The bottom layer of A and B uses a savepoint mechanism to form nested transactions.

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

<!-- Configure transaction notification -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="edit*" propagation="REQUIRED" />
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="new*" propagation="REQUIRED" />
<tx:method name="set*" propagation="REQUIRED" />
<tx:method name="remove*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="change*" propagation="REQUIRED" />
<tx:method name="get*" propagation="REQUIRED" read-only="true" />
<tx:method name="find*" propagation="REQUIRED" read-only="true" />
<tx:method name="load*" propagation="REQUIRED" read-only="true" />
<tx:method name="*" propagation="REQUIRED" read-only="true" />
</tx:attributes>
</tx:advice>

<!-- Configuration transaction aspect -->
<aop:config>
<!-- Configuration cut point -->
<aop:pointcut id="serviceMethod" expression="execution(* com.java1234.service.*.*(..))" />
<!-- Configure transaction notification -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod"/>
</aop:config>

2. Isolation level: defines the degree to which a transaction may be affected by other concurrent transactions.

  Problems caused by concurrent transactions:

  In a typical application, multiple transactions run concurrently, often operating the same data to complete their tasks. Although concurrency is necessary, it may cause the following problems.

    ① Dirty reads-Dirty reads occur when one transaction reads data that has been rewritten by another transaction but has not yet been committed. If the rewrite is rolled back later, the data obtained by the first transaction is invalid.

    ② Nonrepeatable read-nonrepeatable read occurs when a transaction executes the same query twice or more, but each time it gets different data. This is usually because another concurrent transaction was updated during the two queries.

    ③ Phantom read-Phantom read is similar to non-repeatable read. It occurs when a transaction (T1) reads a few rows of data, and then another concurrent transaction (T2) inserts some data. In subsequent queries, the first transaction (T1) will find that there are more records that did not exist.

Note: The focus of non-repeatable reading is modification, while the focus of phantom reading is adding or deleting.

 In Spring transaction management, the following isolation levels are defined for us:

  ① ISOLATION_DEFAULT: Use the default isolation level of the back-end database

  ② ISOLATION_READ_UNCOMMITTED: the lowest isolation level, allowing to read data changes that have not yet been committed, which may cause dirty reads, phantom reads or non-repeatable reads

  ③ ISOLATION_READ_COMMITTED: Allows to read the data submitted by concurrent transactions, which can prevent dirty reads, but phantom reads or non-repeatable reads may still occur

  ④ ISOLATION_REPEATABLE_READ: The results of multiple reads of the same field are consistent, unless the data is modified by the transaction itself, which can prevent dirty reads and non-repeatable reads, but phantom reads may still occur

  ⑤ ISOLATION_SERIALIZABLE: The highest isolation level, fully compliant with the ACID isolation level, to ensure that dirty reads, non-repeatable reads, and phantom reads are prevented, and it is also the slowest transaction isolation level, because it is usually achieved by completely locking transaction-related database tables of

  The isolation levels defined above are also represented by constants -1,0,1,2,4,8 in Spring's TransactionDefinition.class.

3.read only

  This is the third characteristic of the transaction, whether it is a read-only transaction. If the transaction only performs this operation on the back-end database, the database can use the read-only feature of the transaction to perform some specific optimizations. By setting the transaction as read-only, you can give the database a chance to apply the optimization measures it thinks are appropriate.

  4.transaction timeout

  In order for the application to run well, the transaction cannot run for too long. Because transactions may involve locks on the back-end database, long-term transactions will unnecessarily occupy database resources. Transaction timeout is a timer of the transaction. If the transaction is not completed within a certain period of time, it will automatically roll back instead of waiting for its end.

  5.rollback rules

  The last aspect of the transaction pentagon is a set of rules that define which exceptions will cause the transaction to roll back and which will not. By default, the transaction will only roll back when it encounters a runtime exception, and will not roll back when it encounters a checked exception (this behavior is consistent with the rollback behavior of EJB). But you can declare that the transaction rolls back as it encounters a runtime exception when it encounters a specific checked exception. Similarly, you can also declare that the transaction will not roll back when encountering specific exceptions, even if these exceptions are runtime exceptions.

Declarative transaction processing realizes transfer (based on AOP annotation configuration) 

Divided into the following two steps:

  ① Configure the transaction manager in applicationContext.xml, and hand it over to spring

  ② Add annotations to the target class or target method @Transactional

  First configure the following in the applicationContext.xml file:

<!-- 1 Transaction Manager -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 2 Hand over the manager to spring
* transaction-manager configuration transaction manager
* proxy-target-class
true: the underlying cglib proxy is mandatory
-->
<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>

Secondly, add annotation @Transactional to the target class or method. If you add it to the class, it means that all methods in the class add a transaction. If you add it to a method, only that method has a transaction.

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.my.dao.AccountDao;
import com.my.service.AccountService;

@Transactional(propagation=Propagation.REQUIRED , isolation = Isolation.DEFAULT)
@Service("accountService")
public class AccountServiceImpl implements AccountService{
@Resource(name="accountDao")
private AccountDao accountDao;

public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public void transfer(String outer, String inner, int money) {
accountDao.out(outer, money);
//int i = 1/0;
accountDao.in(inner, money);
}

}

Spring support for jdbc

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

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>

<context:property-placeholder location="jdbc.properties"/>

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>


<bean id="studentDao" class="com.java1234.dao.impl.StudentDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>

<bean id="studentService" class="com.java1234.service.impl.StudentServiceImpl">
<property name="studentDao" ref="studentDao"></property>
</bean>

</beans>

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db_spring
jdbc.username=root
jdbc.password=123456

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCallbackHandler;


public class StudentDaoImpl implements StudentDao{

private JdbcTemplate jdbcTemplate;

public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}

@Override
public int addStudent(Student student) {
String sql="insert into t_student values(null,?,?)";
Object []params=new Object[]{student.getName(),student.getAge()};
return jdbcTemplate.update(sql,params);
}

@Override
public int updateStudent(Student student) {
String sql="update t_student set name=?,age=? where id=?";
Object []params=new Object[]{student.getName(),student.getAge(),student.getId()};
return jdbcTemplate.update(sql,params);
}

@Override
public int deleteStudent(int id) {
String sql="delete from t_student where id=?";
Object []params=new Object[]{id};
return jdbcTemplate.update(sql,params);
}

@Override
public List<Student> findStudents() {
String sql="select * from t_student";
final List<Student> studentList=new ArrayList<Student>();
jdbcTemplate.query(sql, new RowCallbackHandler(){

@Override
public void processRow(ResultSet rs) throws SQLException {
Student student=new Student();
student.setId(rs.getInt("id"));
student.setName(rs.getString("name"));
student.setAge(rs.getInt("age"));
studentList.add(student);
}

});
return studentList;
}

}

import java.util.List;

public class StudentServiceImpl implements StudentService{

private StudentDao studentDao;

public void setStudentDao(StudentDao studentDao) {
this.studentDao = studentDao;
}

@Override
public int addStudent(Student student) {
return studentDao.addStudent(student);
}

@Override
public int updateStudent(Student student) {
return studentDao.updateStudent(student);
}

@Override
public int deleteStudent(int id) {
return studentDao.deleteStudent(id);
}

@Override
public List<Student> findStudents() {
return studentDao.findStudents();
}

import java.util.List;

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class T {

private ApplicationContext ac;

@Before
public void setUp() throws Exception {
ac=new ClassPathXmlApplicationContext("beans.xml");
}

@Test
public void addStudent() {
StudentService studentService=(StudentService)ac.getBean("studentService");
int addNums=studentService.addStudent(new Student("Joe", 1));
if(addNums==1){
System.out.println("Added successfully");
}
}
To
@Test
public void updateStudent() {
StudentService studentService=(StudentService)ac.getBean("studentService");
int updateNums=studentService.updateStudent(new Student(8,"Joe2", 2));
if(updateNums==1){
System.out.println("Updated successfully");
}
}
To
@Test
public void deleteStudent() {
StudentService studentService=(StudentService)ac.getBean("studentService");
int deleteNums=studentService.deleteStudent(8);
if(deleteNums==1){
System.out.println("Delete successfully");
}
}
To
@Test
public void findStudents() {
StudentService studentService=(StudentService)ac.getBean("studentService");
List<Student> studentList=studentService.findStudents();
for(Student student:studentList){
System.out.println(student);
}
}

}

Support named parameter variables

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

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>

<context:property-placeholder location="jdbc.properties"/>

<bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="dataSource"></constructor-arg>
</bean>


<bean id="studentDao" class="com.java.dao.impl.StudentDaoImpl">
<property name="namedParameterJdbcTemplate" ref="namedParameterJdbcTemplate"></property>
</bean>

<bean id="studentService" class="com.java.service.impl.StudentServiceImpl">
<property name="studentDao" ref="studentDao"></property>
</bean>

</beans>

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

public class StudentDaoImpl implements StudentDao{

private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

public void setNamedParameterJdbcTemplate(
NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
}

@Override
public int addStudent(Student student) {
String sql="insert into t_student values(null,:name,:age)";
MapSqlParameterSource sps=new MapSqlParameterSource();
sps.addValue("name", student.getName());
sps.addValue("age", student.getAge());
return namedParameterJdbcTemplate.update(sql,sps);
}

@Override
public int updateStudent(Student student) {
String sql="update t_student set name=:name,age=:age where id=:id";
MapSqlParameterSource sps=new MapSqlParameterSource();
sps.addValue("name", student.getName());
sps.addValue("age", student.getAge());
sps.addValue("id", student.getId());
return namedParameterJdbcTemplate.update(sql,sps);
}

@Override
public int deleteStudent(int id) {
String sql="delete from t_student where id=:id";
MapSqlParameterSource sps=new MapSqlParameterSource();
sps.addValue("id", id);
return namedParameterJdbcTemplate.update(sql,sps);
}

@Override
public List<Student> findStudents() {
String sql="select * from t_student";
final List<Student> studentList=new ArrayList<Student>();
namedParameterJdbcTemplate.query(sql, new RowCallbackHandler(){

@Override
public void processRow(ResultSet rs) throws SQLException {
Student student=new Student();
student.setId(rs.getInt("id"));
student.setName(rs.getString("name"));
student.setAge(rs.getInt("age"));
studentList.add(student);
}

});
return studentList;
}

}

import java.util.List;

public class StudentServiceImpl implements StudentService{

private StudentDao studentDao;

public void setStudentDao(StudentDao studentDao) {
this.studentDao = studentDao;
}

@Override
public int addStudent(Student student) {
return studentDao.addStudent(student);
}

@Override
public int updateStudent(Student student) {
return studentDao.updateStudent(student);
}

@Override
public int deleteStudent(int id) {
return studentDao.deleteStudent(id);
}

@Override
public List<Student> findStudents() {
return studentDao.findStudents();
}
}

Spring integrates hibernate

web,xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http ://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>S2SH</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

<!-- Add support for spring -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>

<!-- Define Spring listener, load Spring -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- Add support for struts2 -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- Session delay loading to the page -->
<filter>
<filter-name>openSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>singleSession</param-name>
<param-value>true</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>openSessionInViewFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
</web-app>

struts.xml

<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>
<constant name="struts.action.extension" value="action" />

<package name="s2sh" namespace="/user" extends="struts-default">
<action name="user_*" method="{1}" class="com.java.action.UserAction">
<result name="success">/success.jsp</result>
<result name="error">/index.jsp</result>
</action>
</package>

</struts>

hibernate.cfg.xml

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
To
<!-- Dialect-->
<property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>

<!-- Display sql statement -->
<property name="show_sql">true</property>

<!-- Automatic update -->
<property name="hbm2ddl.auto">update</property>


</session-factory>
</hibernate-configuration>

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

<!-- Define data source -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"
value="com.mysql.jdbc.Driver">
</property>
<property name="url"
value="jdbc:mysql://localhost:3306/test">
</property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
</bean>

<!-- session factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="configLocation" value="classpath:hibernate.cfg.xml"/>
<!-- Automatically scan hibernate class files configured in annotation mode -->
<property name="packagesToScan">
<list>
<value>com.java.entity</value> //All classes under the package will be scanned
</list>
</property>
</bean>

<!-- Configure Transaction Manager -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>

<!-- Configure transaction notification properties -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- Define transaction propagation attributes -->
<tx:attributes>
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="edit*" propagation="REQUIRED" />
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="new*" propagation="REQUIRED" />
<tx:method name="set*" propagation="REQUIRED" />
<tx:method name="remove*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="change*" propagation="REQUIRED" />
<tx:method name="get*" propagation="REQUIRED" read-only="true" />
<tx:method name="find*" propagation="REQUIRED" read-only="true" />
<tx:method name="load*" propagation="REQUIRED" read-only="true" />
<tx:method name="*" propagation="REQUIRED" read-only="true" />
</tx:attributes>
</tx:advice>


<!-- Configuration transaction aspect -->
<aop:config>
<aop:pointcut id="serviceOperation"
expression="execution(* com.java.service..*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation" />
</aop:config>

<!-- Automatically load the build bean -->
<context:component-scan base-package="com.java" /> //All configured classes are annotated

</beans>

entity

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(name="t_user")
public class User {

private Integer id;
private String userName;
private String password;


@Id
@GenericGenerator(name = "generator", strategy = "native")
@GeneratedValue(generator = "generator")
@Column(name = "id", length=11)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(name = "userName", length = 20)
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
@Column(name = "password", length = 20)
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}

}

import java.io.Serializable;
import java.util.List;

/**
* Basic database operations
*
*
*/
public interface BaseDao<T> {

/**
* Save an object
*
* @param o
* @return
*/
public Serializable save(T o);

/**
* Delete an object
*
* @param o
*/
public void delete(T o);

/**
* Update an object
*
* @param o
*/
public void update(T o);

/**
* Save or update objects
*
* @param o
*/
public void saveOrUpdate(T o);

/**
* Inquire
*
* @param hql
* @return
*/
public List<T> find(String hql);

/**
* Query collection
*
* @param hql
* @param param
* @return
*/
public List<T> find(String hql, Object[] param);

/**
* Query collection
*
* @param hql
* @param param
* @return
*/
public List<T> find(String hql, List<Object> param);

/**
* Query collection (with pagination)
*
* @param hql
* @param param
* @param page
* Check the page
* @param rows
* Display several records per page
* @return
*/
public List<T> find(String hql, Object[] param, Integer page, Integer rows);

/**
* Query collection (with pagination)
*
* @param hql
* @param param
* @param page
* @param rows
* @return
*/
public List<T> find(String hql, List<Object> param, Integer page, Integer rows);

/**
* Get an object
*
* @param c
* Object type
* @param id
* @return Object
*/
public T get(Class<T> c, Serializable id);

/**
* Get an object
*
* @param hql
* @param param
* @return Object
*/
public T get(String hql, Object[] param);

/**
* Get an object
*
* @param hql
* @param param
* @return
*/
public T get(String hql, List<Object> param);

/**
* select count(*) from class
*
* @param hql
* @return
*/
public Long count(String hql);

/**
* select count(*) from class
*
* @param hql
* @param param
* @return
*/
public Long count(String hql, Object[] param);

/**
* select count(*) from class
*
* @param hql
* @param param
* @return
*/
public Long count(String hql, List<Object> param);

/**
* Execute HQL statement
*
* @param hql
* @return number of responses
*/
public Integer executeHql(String hql);

/**
* Execute HQL statement
*
* @param hql
* @param param
* @return number of responses
*/
public Integer executeHql(String hql, Object[] param);

/**
* Execute HQL statement
*
* @param hql
* @param param
* @return
*/
public Integer executeHql(String hql, List<Object> param);

}

BaseDaOImpl.java

import java.io.Serializable;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository("baseDao")
@SuppressWarnings("all")
public class BaseDaOImpl<T> implements BaseDao<T> {

private SessionFactory sessionFactory;

public SessionFactory getSessionFactory() {
return sessionFactory;
}

@Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}

private Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}

public Serializable save(T o) {
return this.getCurrentSession().save(o);
}

public void delete(T o) {
this.getCurrentSession().delete(o);
}

public void update(T o) {
this.getCurrentSession().update(o);
}

public void saveOrUpdate(T o) {
this.getCurrentSession().saveOrUpdate(o);
}

public List<T> find(String hql) {
return this.getCurrentSession().createQuery(hql).list();
}

public List<T> find(String hql, Object[] param) {
Query q = this.getCurrentSession().createQuery(hql);
if (param != null && param.length > 0) {
for (int i = 0; i < param.length; i++) {
q.setParameter(i, param[i]);
}
}
return q.list();
}

public List<T> find(String hql, List<Object> param) {
Query q = this.getCurrentSession().createQuery(hql);
if (param != null && param.size() > 0) {
for (int i = 0; i < param.size(); i++) {
q.setParameter(i, param.get(i));
}
}
return q.list();
}

public List<T> find(String hql, Object[] param, Integer page, Integer rows) {
if (page == null || page < 1) {
page = 1;
}
if (rows == null || rows < 1) {
rows = 10;
}
Query q = this.getCurrentSession().createQuery(hql);
if (param != null && param.length > 0) {
for (int i = 0; i < param.length; i++) {
q.setParameter(i, param[i]);
}
}
return q.setFirstResult((page - 1) * rows).setMaxResults(rows).list();
}

public List<T> find(String hql, List<Object> param, Integer page, Integer rows) {
if (page == null || page < 1) {
page = 1;
}
if (rows == null || rows < 1) {
rows = 10;
}
Query q = this.getCurrentSession().createQuery(hql);
if (param != null && param.size() > 0) {
for (int i = 0; i < param.size(); i++) {
q.setParameter(i, param.get(i));
}
}
return q.setFirstResult((page - 1) * rows).setMaxResults(rows).list();
}

public T get(Class<T> c, Serializable id) {
return (T) this.getCurrentSession().get(c, id);
}

public T get(String hql, Object[] param) {
List<T> l = this.find(hql, param);
if (l != null && l.size() > 0) {
return l.get(0);
} else {
return null;
}
}

public T get(String hql, List<Object> param) {
List<T> l = this.find(hql, param);
if (l != null && l.size() > 0) {
return l.get(0);
} else {
return null;
}
}

public Long count(String hql) {
return (Long) this.getCurrentSession().createQuery(hql).uniqueResult();
}

public Long count(String hql, Object[] param) {
Query q = this.getCurrentSession().createQuery(hql);
if (param != null && param.length > 0) {
for (int i = 0; i < param.length; i++) {
q.setParameter(i, param[i]);
}
}
return (Long) q.uniqueResult();
}

public Long count(String hql, List<Object> param) {
Query q = this.getCurrentSession().createQuery(hql);
if (param != null && param.size() > 0) {
for (int i = 0; i < param.size(); i++) {
q.setParameter(i, param.get(i));
}
}
return (Long) q.uniqueResult();
}

public Integer executeHql(String hql) {
return this.getCurrentSession().createQuery(hql).executeUpdate();
}

public Integer executeHql(String hql, Object[] param) {
Query q = this.getCurrentSession().createQuery(hql);
if (param != null && param.length > 0) {
for (int i = 0; i < param.length; i++) {
q.setParameter(i, param[i]);
}
}
return q.executeUpdate();
}

public Integer executeHql(String hql, List<Object> param) {
Query q = this.getCurrentSession().createQuery(hql);
if (param != null && param.size() > 0) {
for (int i = 0; i < param.size(); i++) {
q.setParameter(i, param.get(i));
}
}
return q.executeUpdate();
}

}

public interface UserService {

public void saveUser(User user);

public void updateUser(User user);

public User findUserById(int id);

public void deleteUser(User user);

public List<User> findAllList();

public User findUserByNameAndPassword(User user);
}

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.java.dao.BaseDao;
import com.java.entity.User;
import com.java.service.UserService;

@Service("userService")
public class UserServiceImpl implements UserService{

@Resource
private BaseDao<User> baseDao;

@Override
public void saveUser(User user) {
// TODO Auto-generated method stub
baseDao.save(user);
}

@Override
public void updateUser(User user) {
// TODO Auto-generated method stub
baseDao.update(user);
}

@Override
public User findUserById(int id) {
return baseDao.get(User.class, id);
}

@Override
public void deleteUser(User user) {
baseDao.delete(user);
}

@Override
public List<User> findAllList() {
return baseDao.find("from User");
}

@Override
public User findUserByNameAndPassword(User user) {
return baseDao.get("from User u where u.userName=? and u.password=?", new Object[]{user.getUserName(),user.getPassword()});
}

}

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.struts2.interceptor.ServletRequestAware;
import org.springframework.stereotype.Controller;

import com.opensymphony.xwork2.ActionSupport;

@Controller
public class UserAction extends ActionSupport implements ServletRequestAware{

/**
*
*/
private static final long serialVersionUID = 1L;
To
private HttpServletRequest request;

@Resource
private UserService userService;
To
private User user;
private String error;
To
To
To
public User getUser() {
return user;
}



public void setUser(User user) {
this.user = user;
}



public String getError() {
return error;
}



public void setError(String error) {
this.error = error;
}


public String login()throws Exception{
HttpSession session=request.getSession();
User currentUser=userService.findUserByNameAndPassword(user);
if(currentUser!=null){
session.setAttribute("currentUser", currentUser);
return SUCCESS;
}else{
error="The username or password is wrong!";
return ERROR;
}
}

@Override
public void setServletRequest(HttpServletRequest request) {
// TODO Auto-generated method stub
this.request=request;
}

}

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/user/user_login.action" method="post">
userName:<input type="text" name="user.userName" value="${user.userName }"/><br/>
password:<input type="password" name="user.password" value="${user.password }"><br/>
<input type="submit" value="login"/><font color="red">${error }</font>
</form>
</body>
</html>

Spring framework construction

web,xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>prodatashow</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/spring*.xml</param-value>
</context-param>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet>
<servlet-name>AuthImg</servlet-name>
<servlet-class>com.platform.utils.AuthImg</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AuthImg</servlet-name>
<url-pattern>/authImage</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>/cusviews/index</welcome-file>
</welcome-file-list>
<error-page>
<error-code>404</error-code>
<location>/404Error</location>
</error-page>
</web-app>

spring-mvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">

<!-- Auto scan -->
<context:component-scan base-package="com.**.controller">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
</context:component-scan>

<!-- <mvc:annotation-driven /> -->

<!-- Start of static resources -->
<mvc:resources location="/404Error.html" mapping="/404Error.html"/>
<mvc:resources location="/view/**" mapping="/view/**"/>
<mvc:resources location="/application/**" mapping="/application/**"/>
<mvc:resources mapping="/platform/**" location="/platform/,classpath:/platform/" />
<mvc:resources mapping="/favicon.ico" location="/favicon.ico,classpath:/favicon.ico" />
<!-- End of static resources -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/" />
<mvc:exclude-mapping path="/login" />
<mvc:exclude-mapping path="/loginCheck" />
<mvc:exclude-mapping path="/view/**" />
<mvc:exclude-mapping path="/platform/**" />
<mvc:exclude-mapping path="/application/**" />
<bean class="com.interceptor.CusViewsInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
To
<!--Avoid downloading files when returning JSON when IE executes AJAX -->
<bean id="mappingJacksonHttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" value="#{jsonUtils.mapper}"/> <!-- Used for date output format conversion -->
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>*; charset=UTF-8</value>
</list>
</property>
</bean>
To
<!-- Custom intercept processing class -->
<bean id="cntenAccessInterceptor" class="com.platform.framework.web.interceptor.implAccessInterceptor"></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list>
<ref bean="cntenAccessInterceptor" />
</list>
</property>
</bean>
To
<!-- Start the annotation function of SpringMVC, complete the mapping of request and annotation POJO -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="mappingJacksonHttpMessageConverter" /> <!-- JSON converter -->
</list>
</property>
</bean>
To
<!-- jsp view resolution-->
<bean id="jspResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- My understanding of the configuration here is to automatically add a prefix and suffix to the string returned by the subsequent action method to become a usable URL address -->
<property name="contentType" value="text/html;charset=UTF-8"/>
<property name="prefix" value="/" />
<property name="suffix" value=".jsp" />
<property name="order" value="1"/>
</bean>
To
<!-- Configuration of freemarker -->
<bean id="freemarkerConfigurer" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPaths">
<list>
<value>/view</value>
</list>
</property>
<property name="defaultEncoding" value="UTF-8" />
<property name="freemarkerVariables">
<map>
<entry key="downSelector" value-ref="downSelectorDirective"/>
<entry key="checkBox" value-ref="checkBoxDirective"/>
<entry key="redioBox" value-ref="redioBoxDirective"/>
<entry key="popSelector" value-ref="popSelectorDirective"/>
<entry key="uploadPlugin" value-ref="uploadPluginDirective"/>
</map>
</property>
<property name="freemarkerSettings">
<props>
<prop key="template_update_delay">10</prop>
<prop key="locale">zh_CN</prop>
<prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop>
<prop key="date_format">yyyy-MM-dd</prop>
<prop key="number_format">#.##</prop>
</props>
</property>
</bean>
To
<bean id="freemarkerResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="cache" value="true" />
<property name="suffix" value=".html" />
<property name="order" value="

spring-common.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">

<!-- Import configuration file -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<!-- <property name="location" value="classpath*:config/*.properties" /> -->
<property name="locations">
<list>
<value>classpath:config/cache.properties</value>
<value>classpath:config/jdbc.properties</value>
<value>classpath:config/upload.properties</value>
</list>
</property>
</bean>

<!-- Date processing time class -->
<bean id="jsonUtils" class="com.platform.utils.JsonUtil" lazy-init="false"/>
To
<!-- Bean Manager -->
<bean id="springContextHolder" class="com.platform.framework.context.SpringContextHolder" lazy-init="false"/>
To
<!-- http session processing class -->
<bean id="httpSessionService" class="com.platform.framework.session.impl.HttpSessionService" lazy-init="false"/>
To
<!-- Cache processing class -->
<bean id="ehCacheManagerImpl" class="com.platform.framework.cache.impl.EhCacheManagerImpl" lazy-init="false"/>
<bean id="redisCacheManagerImpl" class="com.platform.framework.cache.impl.RedisCacheManagerImpl" lazy-init="false"/>
<bean id="cacheManager" class="net.sf.ehcache.CacheManager" lazy-init="false"/>
To
<!-- Spring and MyBatis integration, no need for mybatis configuration mapping file -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dynamicDataSource" />
<property name="databaseIdProvider" ref="databaseIdProvider" />
<property name="configLocation" value="classpath:config/mybatis-config.xml"></property>
<!-- Automatically scan the mapping.xml file -->
<property name="mapperLocations" value="classpath*:com/cnten/**/mapping/*.xml"></property>
</bean>
To
<!-- The name of the package where the DAO interface is located, Spring will automatically find the classes under it -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.**.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
To
<!-- Scan all Servcie classes -->
<context:component-scan base-package="com.**.service" />
<context:component-scan base-package="com.platform.common.job" />
To
<!-- Automatically scan components configured through annotations under the package com.common.aop and its subpackages -->
<context:component-scan base-package="com.platform.framework"/>
To
<!-- Activate automatic proxy function -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--
properties, settings, typeAliases, typeHandlers,
objectFactory, objectWrapperFactory, reflectorFactory,
plugins, environments, databaseIdProvider, mappers
-->
<configuration>

<!-- Setting management -->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- Print query statement -->
<setting name="logImpl" value="com.commonLogger" />
<setting name="callSettersOnNulls" value="true"/>
<setting name="jdbcTypeForNull" value="NULL"/>
</settings>

<!-- map hump handling -->
<objectWrapperFactory type="com.platform.framework.mybatis.map.MapWrapperFactory"/>

<!-- Plug-in management -->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
</configuration>

import org.apache.ibatis.logging.Log;

public class commonLogger implements Log {
public commonLogger(String clazz) {
}

public boolean isDebugEnabled() {
return true;
}

public boolean isTraceEnabled() {
return false;
}

public void error(String s, Throwable e) {
System.err.println(s);
e.printStackTrace(System.err);
}

public void error(String s) {
System.err.println(s);
}

public void debug(String s) {
System.out.println(s);
}

public void trace(String s) {
System.out.println(s);
}

public void warn(String s) {
System.out.println(s);
}
}

import java.util.Map;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.wrapper.ObjectWrapper;
import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;

public class MapWrapperFactory
implements ObjectWrapperFactory
{
public boolean hasWrapperFor(Object object)
{
return (object != null) && ((object instanceof Map));
}

public ObjectWrapper getWrapperFor(MetaObject metaObject, Object object)
{
return new commonLoggerMapWrapper(metaObject, (Map)object);
}
}

upload.properties

#================================================ ===========upload config properties=================================== ===========================
## Upload file path path (linux)
#uploadDir=/usr/local/tomcat/upload/
## Upload file path path (window)
uploadDir=D:\\dev_space\\workspaces\\newPlatform\\upload

CommonFreeMarkerView

package com.platform.framework.web.view;

import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.web.servlet.view.freemarker.FreeMarkerView;

import com.platform.consts.Constant;
import com.platform.consts.LoginConstant;

/**
* Override the freemark view parsing class
* @author pzh
*/
public class CommonFreeMarkerView extends FreeMarkerView {
To
@SuppressWarnings("unchecked")
@Override
protected void exposeHelpers(Map<String, Object> model,
HttpServletRequest request) throws Exception {
model.put("context_path", request.getContextPath()); //Context
String act = request.getParameter("act");
String menuCode = request.getParameter("menuCode");
model.put("pageAct", act);
if(Constant.READ.equals(act)) {
model.put("edited", "disabled"); //Operation is prohibited
}else{
model.put("edited", "");
}

//Handle the hiding of page buttons|display
List<Map<String, Object>> authActs = (List<Map<String, Object>>) request.getSession().getAttribute(LoginConstant.LOGIN_USER_AUTH_PERMISSION);
if(authActs !=null && authActs.size()>0) {
for (Map<String, Object> map: authActs) {
String actNo = map.get("actNo").toString();
if(menuCode != null && menuCode.equals(map.get("menuCode"))) {
if(Integer.valueOf(actNo) == 1) {
model.put(String.valueOf(map.get("actCode")), "");
}else{
model.put(String.valueOf(map.get("actCode")), map.get("actCode"));
}
}
}
}
super.exposeHelpers(model, request);
}
To
}

CommonAccessInterceptor

package com.platform.framework.web.interceptor.impl;

import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.platform.framework.context.ThreadContextHolder;
import com.platform.framework.web.interceptor.ILocalInterceptor;

public class CommonAccessInterceptor extends HandlerInterceptorAdapter{
To
@SuppressWarnings("unused")
private ILocalInterceptor localInterceptor; //Local custom interceptor, implemented by business code
To
/**
* Intercept all requests of spring mvc
* And set request and response to thread variables
* Realize request any where
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//Record the request object
ThreadContextHolder.setHttpRequest(request);
ThreadContextHolder.setHttpResponse(response);
To
//Illegal character filtering
Pattern pattern = Pattern.compile("'|<|>");
for(String[] paramValues: request.getParameterMap().values()){
for(String paramValue: paramValues){
if(pattern.matcher(paramValue).find()){
return false;
}
}
}
To
//The parent class only deals with the general part, and the localization business is realized by the specific business
// localInterceptor = SpringContextHolder.getBean("localInterceptor");
// if(null != localInterceptor)
// localInterceptor.preHandle(request, response, handler);
To
return super.preHandle(request, response, handler);
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
super.afterCompletion(request, response, handler, ex);
ThreadContextHolder.clearThreadValues();
}

}

CusViewsInterceptor

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

public class CusViewsInterceptor extends HandlerInterceptorAdapter{
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
super.postHandle(request, response, handler, modelAndView);
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return super.preHandle(request, response, handler);
}
}

log4j.properties

#Define LOG output level ERROR, WARN, INFO, DEBUG
#log4j.rootLogger=INFO,Console,File
log4j.rootLogger=INFO,Console
#Define the log output destination as the console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.Target=System.out
#Can flexibly specify the log output format, the following line is to specify the specific format
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%c]-%m%n
#Generate a new file when the file size reaches the specified size
log4j.appender.File=org.apache.log4j.RollingFileAppender
#Specify the output directory
log4j.appender.File.File=D:/logs/ssm.log
#Define the maximum file size
log4j.appender.File.MaxFileSize=10MB
#Output all logs, if you change to DEBUG, it means output logs of DEBUG or higher
log4j.appender.File.Threshold=ALL
log4j.appender.File.layout=org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern=[%p] [%d{yyyy-MM-dd HH\:mm\:ss}][%c]%m%n
#Control Framework Log
log4j.logger.org.springframework=ERROR
log4j.logger.org.mybatis=ERROR
log4j.logger.org.apache=ERROR

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final static Logger log = LoggerFactory.getLogger(AreaController.class);

import org.apache.log4j.Logger;
import java.text.MessageFormat;
private static Logger logger = Logger.getLogger(WorkManager.class);
logger.info(MessageFormat.format("====sys worker {0} syn date start time:{1}====", ruleCode,
DateUtil.formatTime(now)));

  • Taken
  • add comment
  • 0
Sign In
Sign In
avatar

Java Spring tutorial.

Java Spring tutorial.

bounty icon
$20
Single winner
Asked  9 months ago
Viewed  0 times

I need a enough-to-start-with java spring framework tutorial.

  • add comment
avatar

what is Spring ?

Spring is an open source framework. One of the main advantages of the framework is its layered architecture. The layered architecture allows users to choose which component to use while providing an integrated framework for J2EE application development. Spring uses basic JavaBeans to accomplish things that could only be done by EJB before. However, the use of Spring is not limited to server-side development. From the perspective of simplicity, testability, and loose coupling, any Java application can benefit from Spring. The core of Spring is inversion of control (IoC) and aspect-oriented-programming (AOP).

Spring features

①Convenient decoupling and simplify development

  Through the IoC container provided by Spring, we can hand over the dependencies between objects to Spring to control, avoiding excessive program coupling caused by hard coding. With Spring, users no longer need to write code for very low-level requirements such as single-instance mode classes and property file analysis, and can focus more on upper-level applications.

  ②AOP programming support

  The AOP function provided by Spring facilitates aspect-oriented programming, and many functions that are not easy to implement with traditional OOP can be easily handled by AOP.

  ③ Support for declarative transactions

  In Spring, we can get rid of the monotonous and boring transaction management code, and flexibly manage transactions in a declarative way to improve development efficiency and quality.

  ④convenient program testing

  You can use non-container-dependent programming for almost all testing work. In Spring, testing is no longer an expensive operation, but something that can be done at hand. For example: Spring supports Junit4, so you can easily test Spring programs through annotations.

  ⑤ Convenient integration of various excellent frameworks

  Spring does not exclude various excellent open source frameworks. On the contrary, Spring can reduce the difficulty of using various frameworks. Spring provides direct support for various excellent frameworks (such as Struts, Hibernate, Hessian, Quartz), etc.

  ⑥ Reduce the difficulty of using Java EE API

  Spring provides a thin encapsulation layer for many difficult-to-use Java EE APIs (such as JDBC, JavaMail, remote calls, etc.). Through Spring's simple encapsulation, the difficulty of using these Java EE APIs is greatly reduced.

  ⑦ Java source code is a classic learning example

  Spring's source code design is exquisite, clear in structure, and original ingenuity. It reflects the master's flexible use of Java design patterns and advanced knowledge of Java technology. The Spring framework source code is undoubtedly a best practice example of Java technology. If you want to quickly improve your Java technology level and application development level in a short period of time, learning and studying Spring source code will make you receive unexpected results.

Spring framework structure

Image for question

1. Core container: The core container provides the basic functions of the Spring framework (Spring Core). The main component of the core container is BeanFactory, which is the realization of the factory pattern. BeanFactory uses the Inversion of Control (IOC) model to separate the configuration and dependency specifications of the application from the actual application code.

  2. Spring context: Spring context is a configuration file that provides context information to the Spring framework. The Spring context includes enterprise services such as JNDI, EJB, e-mail, internationalization, verification and scheduling functions.

  3. Spring AOP: Through the configuration management feature, the Spring AOP module directly integrates the aspect-oriented programming function into the Spring framework. Therefore, any object managed by the Spring framework can easily support AOP. The Spring AOP module provides transaction management services for objects in Spring-based applications. By using Spring AOP, you can integrate declarative transaction management into your application without relying on EJB components.

  4. Spring DAO: The JDBCDAO abstraction layer provides a meaningful exception hierarchy, which can be used to manage exception handling and error messages thrown by different database vendors. The exception hierarchy simplifies error handling and greatly reduces the amount of exception code that needs to be written (such as opening and closing connections). Spring DAO's JDBC-oriented exceptions follow the general DAO exception hierarchy.

  5. Spring ORM: Spring framework inserts several ORM frameworks, thus providing ORM object relation tools, including JDO, Hibernate and iBatisSQL Map. All of these follow Spring's general transaction and DAO exception hierarchy.

  6. Spring Web module: The Web context module is built on top of the application context module to provide context for Web-based applications. Therefore, the Spring framework supports integration with Jakarta Struts. The web module also simplifies the work of processing multipart requests and binding request parameters to domain objects.

  7. Spring MVC framework: MVC framework is a full-featured MVC implementation for building Web applications. Through the strategy interface, the MVC framework becomes highly configurable. MVC accommodates a large number of view technologies, including JSP, Velocity, Tiles, iText, and POI. The model is composed of javabean and stored in the Map; the view is an interface, responsible for displaying the model; the controller represents the logic code and is the realization of the Controller. The features of the Spring framework can be used in any J2EE server, and most features are also applicable to unmanaged environments. The core point of Spring is to support reusable business and data access objects that are not bound to specific J2EE services. There is no doubt that such objects can be reused between different J2EE environments (Web or EJB), stand-alone applications, and test environments.

Spring framework features

Lightweight-Spring is lightweight in terms of size and overhead. The complete Spring framework can be published in a JAR file that is only 1MB in size. And the processing overhead required by Spring is also negligible. In addition, Spring is non-intrusive: Typically, objects in Spring applications do not depend on Spring's specific classes.

  Inversion of Control-Spring promotes low coupling through a technique called Inversion of Control (IoC). When IoC is applied, other objects that an object depends on will be passed in passively, instead of creating or finding dependent objects by itself. You can think of IoC as the opposite of JNDI—it's not that the object looks for dependencies from the container, but the container actively passes the dependencies to it when the object is initialized without waiting for the object's request.

  Aspect-oriented-Spring provides rich support for aspect-oriented programming, allowing cohesive development by separating application business logic and system-level services (such as auditing and transaction management). Application objects only implement what they are supposed to do-complete business logic-nothing more. They are not responsible (or even aware of) other system-level concerns, such as logging or transaction support.

  Container-Spring contains and manages the configuration and life cycle of application objects. In this sense, it is a container. You can configure how each of your beans is created-based on a configurable prototype, your bean You can create a single instance or generate a new instance every time you need it-and how they are related to each other. However, Spring should not be confused with traditional heavyweight EJB containers. They are often large and heavy and difficult to use.

  Framework-Spring can configure and combine simple components into complex applications. In Spring, application objects are combined declaratively, typically in an XML file. Spring also provides many basic functions (transaction management, persistence framework integration, etc.), leaving the development of application logic to you.

  MVC-The role of Spring is integration, but it is not limited to integration. The Spring framework can be regarded as an enterprise solution-level framework. The client sends the request, and the server controller (implemented by DispatcherServlet) completes the forwarding of the request. The controller calls a class HandlerMapping for mapping, which is used to map the request to the corresponding processor to process the request. HandlerMapping maps the request to the corresponding processor Controller (equivalent to Action). In Spring, if you write some processor components, generally implement the Controller interface, you can call some Service or DAO in the Controller to perform data operations. ModelAndView is used to store the slave DAO The data retrieved can also store some data of the response view. If you want to return the processing result to the user, a view component ViewResolver is also provided in the Spring framework. The component finds the corresponding view according to the indicator returned by the Controller, and returns the response to the user.

Spring advantages

Spring can effectively organize your middle-tier objects, regardless of whether you choose to use EJB. If you only use Struts or other frameworks that contain J2EE-specific APIs, you will find that Spring pays attention to the remaining problems. Spring can eliminate the excessive use of Singleton in many projects. According to my experience, this is a major problem, which reduces the testability and object-oriented characteristics of the system.

  Spring can eliminate the need to use various formats of attribute customization files, and can be configured in a consistent way throughout the application and project. Have you ever felt confused, a particular class has to look for psychedelic attribute keywords or system attributes, do you have to read Javadoc or even the source code? With Spring, you can easily see the JavaBean properties of a class.

  Spring can promote good programming habits through interfaces instead of classes, reducing programming costs to almost zero.

  Spring is designed to make applications created with it rely as little as possible on its APIs. Most business objects in Spring applications do not depend on Spring. So applications built with Spring are easy to unit test.

  Spring can make the use of EJB an implementation choice, rather than an inevitable choice for application architecture. You can choose to use POJOs or local EJBs to implement business interfaces without affecting the calling code.

  Spring helps you solve many problems without using EJB. Spring can provide an alternative to EJB, which is suitable for many web applications. For example, Spring can use AOP to provide declarative transactions without using an EJB container. If you only need to deal with a single database, you don't even need to implement JTA.

  Spring provides a consistent framework for data access, whether using JDBC or O/R mapping products (such as Hibernate).

  to sum up:

  1. Low intrusive design, extremely low code pollution

  2. Independent of various application servers, applications based on the Spring framework can truly realize the promise of Write Once and Run Anywhere

  3. Spring's DI mechanism reduces the complexity of business object replacement and improves the decoupling between components

  4. Spring's AOP support allows centralized management of some common tasks such as security, transactions, logs, etc., thereby providing better reuse

  5. Spring's ORM and DAO provide good integration with third-party persistence layer frameworks, and simplify the underlying database access

  6. Spring does not force applications to be completely dependent on Spring, developers are free to choose part or all of the Spring framework

IOC-Inversion of Control, that is, inversion of control. It is not a technology, but a design idea.

  The traditional method of creating objects is directly through the new keyword , while spring creates objects through the IOC container, which means that we give the control of creating objects to the IOC container. We can summarize IOC in one sentence:

  IOC allows programmers not to pay attention to how to create objects, but to focus on operations after object creation, and delegate the creation, initialization, and destruction of objects to the spring container.

Three ways to create objects in Spring containers

//This is the test object, we create the object through IOC
public class HelloIoc {

public void sayHello(){
System.out.println("Hello IOC");
}
}

The traditional method of creating objects: the new keyword

 @Test
public void testTradition(){
HelloIoc hello = new HelloIoc();
hello.sayHello();
}

The traditional method of creating objects: the new keyword

How to create it through the Spring container here?

  The first method: use the default construction method

  Create a new applicationContext.xml file in the src directory, this is the spring configuration file, add the following code:

<?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
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
The first way to create an object: using a parameterless constructor
id: unique identifier
class: the full class name of the class
-->
<bean id="helloIoc" class="com.my.ioc.HelloIoc" ></bean>
<!-- Alias attribute name: corresponds to the id attribute of the bean -->
<alias name="helloIoc" alias="helloIoc2"/>

</beans>

/**
* Spring container uses constructor to create objects
*/
@Test
public void testCreateObjectByConstrutor(){
//1, start the spring container
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
//2, take out the data from the spring container
HelloIoc IOC = (HelloIoc) context.getBean("helloIoc");
//3, call method through object
IOC.sayHello();

//Use the configuration file alias to create an object
HelloIoc IOC2 = (HelloIoc) context.getBean("helloIoc2");
IOC2.sayHello();
}

Manually add a construction method without parameters in HelloIoc.java, and then execute the above test code, you will find that the construction method will be called before the sayHello() method is executed.

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

<bean id="zhangsan" class="com.java.service.ZhangSan"></bean>
To
<bean id="lisi" class="com.java.service.Lisi"></bean>
To
<bean id="javaWork" class="com.java.service.JavaWork">
<property name="tester" ref="lisi"></property>
</bean>

</beans>

	public static void main(String[] args) {
ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml");
JavaWork javaWork=(JavaWork)ac.getBean("javaWork");
javaWork.doTest();
}

public class JavaWork {

private Tester tester;

public void setTester(Tester tester) {
this.tester = tester;
}

public void doTest(){
tester.test();
}
}

The second method: use the static factory method

  First create the static factory class HelloStaticFactory.java

public class HelloStaticFactory {
public HelloStaticFactory(){
System.out.println("HelloStaticFactory constructor");
}
//Static factory method
public static HelloIoc getInstances(){
return new HelloIoc();
}
}

Then configure the following in applicationContext.xml:

<!--
The second way to create objects: using static factory methods
factory-method: static method of obtaining object of static factory class
class: the full class name of the static factory class
-->
<bean id="helloStaticFactory" factory-method="getInstances" class="com.my.ioc.HelloStaticFactory"></bean>

/**
* The Spring container uses static factory methods to create objects
*/
@Test
public void createObjectStaticFactory(){
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
HelloIoc staticFactory =
(HelloIoc) context.getBean("helloStaticFactory");
staticFactory.sayHello();
}

The spring container is only responsible for calling the static factory method, and the internal implementation of this static factory method is done by the programmer

Using the instance factory method

  First create the instance factory class HelloInstanceFactory.java

public class HelloInstanceFactory {
public HelloInstanceFactory(){
System.out.println("Instance Factory Method Constructor");
}

//Using the instance factory method to create an object
public HelloIoc getInstance(){
HelloIoc instanceIoc = new HelloIoc();
return instanceIoc;
}
}

Then configure the following in applicationContext.xml:

<!--
The third way to create objects: use the instance factory method
factory-bean: Specify the beanID that contains the factory method in the current Spring
factory-method: factory method name
-->
<bean id="instanceFactory" class="com.my.ioc.HelloInstanceFactory"></bean>
<bean id="instance" factory-bean="instanceFactory" factory-method="getInstance"></bean>

/**
* The Spring container uses instance factory methods to create objects
*/
@Test
public void createObjectInstanceFactory(){
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
HelloIoc staticFactory =
(HelloIoc) context.getBean("instance");
staticFactory.sayHello();
}

When to create objects in the Spring container

By default, the object is created when the spring container is started

There is an attribute lazy-init="default/true/false" in the spring configuration file bean

    ① If lazy-init is "default/false", create an object when starting the spring container (default)

     ② If lazy-init is "true", the object must be created in context.getBean

 <bean id="helloIoc" lazy-init=“true” class="com.my.ioc.HelloIoc" ></bean>  

In the first case, you can check the correctness of the spring container configuration file when starting the spring container. If combined with tomcat, if the spring container cannot start normally, the entire tomcat cannot start normally. But the disadvantage of this is that some beans are placed in memory prematurely. If there is data, it will consume memory.

  Conversely, in the second case, memory consumption can be reduced, but it is not easy to find errors

Scope in spring bean: "singleton/prototype/request/session/global session"

1. The default scope value is singleton, that is, the generated object is singleton

  Configuration in the applicationContext.xml file:

<bean id="helloIoc" scope="singleton" class="com.my.ioc.HelloIoc" ></bean>

//The default object generated by spring container is singleton scope="singleton"
@Test
public void test_scope_single_CreateObject(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
HelloIoc hello1 = (HelloIoc) context.getBean("helloIoc");
HelloIoc hello2 = (HelloIoc) context.getBean("helloIoc");
System.out.println(hello1.equals(hello2)); //true
}

scope="prototype"

  Multi-case mode, and the object is not created when the spring container starts, but when the bean is obtained.

Summary: In the singleton mode, the spring container is started, and the object will be created; in the multi-case mode, the container will not be created when the container is started, and the object will be created when the bean is obtained

scope="request" Every HTTP request will create a new bean

scope="session" shares a Bean with the same HTTP Session

scope="global session" The same global Session shares a Bean, which is generally used in portlet application environments

scope="application" The same Application shares a Bean

Spring container life cycle

/**
* The life cycle of the Spring container
* @author hadoop
*
*/
public class SpringLifeCycle {
public SpringLifeCycle(){
System.out.println("SpringLifeCycle");
}
//Define the initialization method
public void init(){
System.out.println("init...");
}
//Define the destruction method
public void destroy(){
System.out.println("destroy...");
}

public void sayHello(){
System.out.println("say Hello...");
}
}

applicationContext.xml

<!-- Life cycle -->
<bean id="springLifeCycle" init-method="init" destroy-method="destroy" class="com.my.ioc.SpringLifeCycle"></bean>

public void testSpringLifeCycle(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
SpringLifeCycle hello = (SpringLifeCycle) context.getBean("springLifeCycle");

hello.sayHello();

//Destroy the spring container
ClassPathXmlApplicationContext classContext = (ClassPathXmlApplicationContext) context;
classContext.close();
}

Life cycle of spring container

     1. The spring container creates an object

  2. Execute the init method

  3. Call your own method

  4. Execute the destroy method when the spring container is closed

  Note: When the scope is "prototype", the destroy method will not be called when the close() method is called

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class T {

private ApplicationContext ac;

@Before
public void setUp() throws Exception {
ac=new ClassPathXmlApplicationContext("beans.xml");
}

@Test
public void test1() {
People people=(People)ac.getBean("people1");
People people2=(People)ac.getBean("people1");
System.out.println(people.getDog()==people2.getDog());

System.out.println(ac.getBean("dog")==ac.getBean("dog"));
}


}

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


<bean id="dog" class="com.java1234.entity.Dog" scope="prototype">
<property name="name" value="Jack"></property>
</bean>



<bean id="people1" class="com.java.entity.People">
<property name="id" value="1"></property>
<property name="name" value="张三"></property>
<property name="age" value="11"></property>
<lookup-method name="getDog" bean="dog"/>//方法动态注入
</bean>

</beans>


public abstract class People {

private int id;
private String name;
private int age;
private Dog dog;
public abstract Dog getDog();

public void setDog(Dog dog) {
this.dog = dog;
}
@Override
public String toString() {
return "People [id=" + id + ", name=" + name + ", age=" + age
+ ", dog=" + dog.getName() + "]";
}

}

Image for question

Method replacement

public class People {

private int id;
private String name;
private int age;
private Dog dog;

public Dog getDog() {
Dog dog=new Dog();
dog.setName("Jack");
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
}

public class People2 implements MethodReplacer {

@Override
public Object reimplement(Object arg0, Method arg1, Object[] arg2)
throws Throwable {
Dog dog=new Dog();
dog.setName("Tom");
return dog;
}

}

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


<bean id="people1" class="com.java.entity.People">
<property name="id" value="1"></property>
<property name="name" value="Joe"></property>
<property name="age" value="11"></property>
<replaced-method name="getDog" replacer="people2"></replaced-method>
</bean>

<bean id="people2" class="com.java.entity.People2"></bean>
</beans>

Image for question

DI dependency injection

Spring dynamically provides an object with other objects it needs. This is achieved through DI (Dependency Injection). For example, object A needs to operate a database. In the past, we always had to write code in A to obtain a Connection object. With spring, we only need to tell spring that a Connection is needed in A. As for how and when this Connection is constructed, A does not need to know. When the system is running, spring will create a Connection at an appropriate time, and then inject it into A like an injection, thus completing the control of the relationship between each object. A needs to rely on Connection to run normally, and this Connection is injected into A by spring, so the name of dependency injection comes from.

import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class Person {
private Long pid;
private String pname;
private Student students;
private List lists;
private Set sets;
private Map maps;
private Properties properties;
}

Assign values ​​in applicationContext.xml

<!--
property is used to describe the properties of a class
Basic types of packaging classes, String and other types that require values ​​are assigned with value
Reference type is assigned with ref
-->
<bean id="person" class="com.my.di.Person">
<property name="pid" value="1"></property>
<property name="pname" value="vae"></property>
<property name="students">
<ref bean="student"/>
</property>
<property name="students" ref="student">//Inject bean
<property name="students.name" value="jack">//cascade private Student students=new Student()

</property>

<property name="lists">
<list>
<value>1</value>
<ref bean="student"/>
<value>vae</value>
</list>
</property>

<property name="sets">
<set>
<value>1</value>
<ref bean="student"/>
<value>vae</value>
</set>
</property>

<property name="maps">
<map>
<entry key="m1" value="1"></entry>
<entry key="m2">
<ref bean="student"/>
</entry>
</map>
</property>

<property name="properties">
<props>
<prop key="p1">p1</prop>
<prop key="p2">p2</prop>
</props>
</property>

</bean>


<bean id="student" class="com.my.di.Student"></bean>

//Use the set method to assign a value to the object
@Test
public void testSet(){
//1, start the spring container
//2, take out the data from the spring container
//3, call method through object
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) context.getBean("person");
System.out.println(person.getPname());//vae
}

Use the constructor to assign values ​​to attributes

Add two construction methods in the entity class Person.java: with and without parameters

//Default constructor
public Person(){}
//Constructor with parameters
public Person(Long pid,Student students){
this.pid = pid;
this.students = students;
}

Assign values ​​in applicationContext.xml

<!-- Assign value according to the constructor -->
<!--
index represents the position of the parameter, starting from 0
type refers to the type of the parameter. When there are multiple constructors, you can use type to distinguish it. If you can determine which constructor is the function, you don’t need to write type
value Assign a value to the basic type
ref assigns a reference type
-->
<bean id="person_con" class="com.my.di.Person">
<constructor-arg index="0" type="java.lang.Long" value="1">
</constructor-arg>
<constructor-arg index="1" type="com.my.di.Student" ref="student_con"></constructor-arg>
</bean>
<bean id="student_con" class="com.my.di.Student"></bean>

//Use the constructor to assign a value to the object
@Test
public void testConstrutor(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) context.getBean("person_con");
System.out.println(person.getPid());//1
}

1. If there is no <constructor-arg> element in the bean in the spring configuration file, the default constructor is called

2. If there is a <constructor-arg> element in the bean in the spring configuration file, the element determines the only constructor

Type injection

public class People {

private int id;
private String name;
private int age;



public People() {
super();
// TODO Auto-generated constructor stub
}




public People(int id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
}


<bean id="people3" class="com.java.entity.People">
<constructor-arg type="int" value="2"></constructor-arg>
<constructor-arg type="String" value="Tom"></constructor-arg>
<constructor-arg type="int" value="22"></constructor-arg>
</bean>

OUTPUT

People [id=2,name=Tom,age=22]

Automatic assembly

byName automatically matches by name

<?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
http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="byName">


<bean id="dog" class="com.java.entity.Dog">
<property name="name" value="Jack"></property>
</bean>


<bean id="dog2" class="com.java.entity.Dog">
<property name="name" value="Joe"></property>
</bean>



<bean id="people1" class="com.java.entity.People">
<property name="id" value="1"></property>
<property name="name" value="Joe"></property>
<property name="age" value="11"></property>

</bean>

</beans>


public class People {

private int id;
private String name;
private int age;
private Dog dog;
}

OUTPUT

People [id=1,name=joe,age=11,dog=Jack]

byType: automatic matching by type

constructor: According to the type, automatic injection

<?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
http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="constructor">

<bean id="dog" class="com.java.entity.Dog">
<property name="name" value="Jack"></property>
</bean>



<bean id="people1" class="com.java.entity.People">
<property name="id" value="1"></property>
<property name="name" value="Joe"></property>
<property name="age" value="11"></property>

</bean>

</beans>


public class People {

private int id;
private String name;
private int age;
private Dog dog;

public People() {
super();
// TODO Auto-generated constructor stub
}

public People(Dog dog) {
super();
System.out.println("constructor");
this.dog = dog;
}
}

OUTPUT

constuctor

Peple [id=1,name=Joe,age=11,doc=Jack]

The relationship between beans

inherit

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

<bean id="dog" class="com.java.entity.Dog">
<property name="name" value="jack"></property>
</bean>

<bean id="abstractPeople" class="com.java.entity.People" abstract="true">
<property name="className" value="Senior"></property>
<property name="age" value="19"></property>
</bean>

<bean id="zhangsan" parent="abstractPeople" depends-on="autority">
<property name="id" value="1"></property>
<property name="name" value="Joe"></property>
</bean>

<bean id="lisi" parent="abstractPeople">
<property name="id" value="2"></property>
<property name="name" value="Tom"></property>
<property name="age" value="20"></property>
<property name="dog" ref="dog"></property>
</bean>


<bean id="autority" class="com.java.service.Authority"></bean>
</beans>

Output:

People [id=1,name=Joe,age=19,className=Senior]

People [id=2,name=Joe,age=20,className=Senior]

rely

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

<bean id="dog" class="com.java.entity.Dog">
<property name="name" value="jack"></property>
</bean>

<bean id="zhangsan" parent="abstractPeople" depends-on="autority">
<property name="id" value="1"></property>
<property name="name" value="Joe"></property>
</bean>

<bean id="lisi" parent="abstractPeople">
<property name="id" value="2"></property>
<property name="name" value="Tom"></property>
<property name="age" value="20"></property>
<property name="dog" ref="dog"></property>
</bean>


<bean id="autority" class="com.java.service.Authority"></bean>
</beans>

OUTPUT

People [id=1,name=Joe,age=19,className = senior]

People [id=2,name=Tom,age=20,className = senior]

Use annotations to let the Spring container generate Person objects for us

Use annotations

Introduce namespace in applicationContext.xml

Image for question

base-package: indicates the name of the package containing the annotation class

If you scan multiple packages, write multiple lines of the above code and change the contents of base-package!

@Component

   If the @Component annotation is added to a class, the following rules will be implemented

      If its value attribute is ""

            @Component

       public class Person {}

Equivalent to

      <bean id="person"class="..Person">

       If the value of its value attribute is not ""

      @Component("p")

      Public classPerson{}

Equivalent to

      <bean id="p"class="..Person">

Add the annotation @Component in the Person class

Image for question
public void testAnnotation(){
//1, start the spring container
//2, take out the data from the spring container
//3, call method through object
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) context.getBean("person");
System.out.println(person.getPname());
}

@Repository :dao layer

@Service:service layer

@Controller:web layer

Annotation @Resource

@Resource annotation, it can annotate class member variables, methods and constructors to complete the work of automatic assembly. Eliminate set and get methods through the use of @Resource.

  After @Resource annotation, judge whether the attribute of the annotation name is "" (name is not written)

  ①If the name attribute is not written, the value of the attribute name will be matched with the value of the ID in the spring configuration file bean (if not configured, it will also be matched with the annotation @Component), if the match is successful, the value will be assigned, if it matches Unsuccessful, it will match according to the spring configuration file class type, if the match is unsuccessful, an error will be reported

  ②If there is a name attribute, it will be matched according to the value of the name attribute and the ID in the spring bean. If the match is successful, the value will be assigned, and if the match is unsuccessful, an error will be reported

Without annotations:

<property name="students">
<ref bean="student"/>
</property>
<bean id="student" class="com.my.annotation_di.Student"></bean>

With annotations:

Image for question

Annotation @Autowired

The function is the same as the annotation @Resource, which can mark class member variables, methods and constructors to complete the work of automatic assembly. It's just that the annotation @Resource is assembled according to the name, while @Autowired is assembled according to the type.

When using @Autowired, first query the corresponding type of bean in the container

    If the query result is exactly one, the bean is assembled to the data specified by @Autowired

    If there is more than one result of the query, @Autowired will search by name.

    If the result of the query is empty, an exception will be thrown. When solving, use required=false

Create interface PersonDao

public interface PersonDao {

public void savePerson();

}

Create an interface implementation class PersonDaoImplOne

import org.springframework.stereotype.Component;

@Component("personDaoImplOne")
public class PersonDaoImplOne implements PersonDao{

@Override
public void savePerson() {
System.out.println("save Person One");

}

}

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("personService")
public class PersonService{
@Autowired
private PersonDao personDao;

public void savePerson() {
this.personDao.savePerson();
}

}

Note: Here we have added the annotation @Autowired to the private PesronDao personDao, it will first match according to the type, PersonDao is an interface, and its implementation class is PesronDaoImpOne, then the meaning here is:

  PersonDao personDao = new PersonDaoImpOne();

  So the question is, what if there are multiple implementation classes for PersonDao? We create the first implementation class PersonDaoImpTwo

The first method: change the name

Image for question

The second method: @Autowired and @Qualifier("name") are used together

Image for question

AOP (Aspect Oriented Programming), usually referred to as aspect-oriented programming. It uses a technique called "cross-cutting" to dissect the inside of the encapsulated object, and encapsulate those common behaviors that affect multiple classes into a reusable module, and name it "Aspect", which is the aspect . The so-called "aspects" are simply those logic or responsibilities that have nothing to do with the business, but are called by business modules, which are encapsulated, which is convenient to reduce the duplication of the system code, reduce the coupling between modules, and facilitate future operability And maintainability.

Static proxy

Both add and delete operations must open the transaction, and commit the transaction after the operation is completed.

public interface UserService {
//add user
public void addUser(User user);
//delete user
public void deleteUser(int uid);
}

Create the implementation class of UserService

public class UserServiceImpl implements UserService{
@Override
public void addUser(User user) {
System.out.println("Add User");
}
@Override
public void deleteUser(int uid) {
System.out.println("Delete User");
}
}

Create transaction class MyTransaction

public class MyTransaction {
//Open transaction
public void before(){
System.out.println("Open transaction");
}
//Submit transaction
public void after(){
System.out.println("Submit transaction");
}
}

Create proxy class ProxyUser.java

public class ProxyUser implements UserService{
//Real class
private UserService userService;
//Transaction class
private MyTransaction transaction;
//Use the constructor to instantiate
public ProxyUser(UserService userService,MyTransaction transaction){
this.userService = userService;
this.transaction = transaction;
}
@Override
public void addUser(User user) {
transaction.before();
userService.addUser(user);
transaction.after();
}
@Override
public void deleteUser(int uid) {
transaction.before();
userService.deleteUser(uid);
transaction.after();
}
}

@Test
public void testOne(){
MyTransaction transaction = new MyTransaction();
UserService userService = new UserServiceImpl();
//Generate a static proxy object
ProxyUser proxy = new ProxyUser(userService, transaction);
proxy.addUser(null);
proxy.deleteUser(0);
}

The business class UserServiceImpl only needs to focus on the business logic itself to ensure the reusability of the business, which is also the advantage of the proxy class

Disadvantages of writing like this:

① An interface of a proxy object only serves one type of object. If there are many proxy methods, it is necessary to proxy each method. Static proxy will not be competent when the program scale is slightly larger.

  ② If the interface adds a method, for example, UserService adds and modifies the updateUser() method, in addition to all implementation classes that need to implement this method, all proxy classes also need to implement this method. Increased the complexity of code maintenance.

Use JDK dynamic proxy

Do not manually generate proxy classes for dynamic proxy. We remove the ProxyUser.java class and add an ObjectInterceptor.java class

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import com.my.aop.one.MyTransaction;

public class ObjectInterceptor implements InvocationHandler{
//Target class
private Object target;
//Aspect class (here refers to transaction class)
private MyTransaction transaction;

//Assign via constructor
public ObjectInterceptor(Object target,MyTransaction transaction){
this.target = target;
this.transaction = transaction;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//Open transaction
this.transaction.before();
//Call the target class method
method.invoke(this.target, args);
//Submit transaction
this.transaction.after();
return null;
}

}

@Test
public void testOne(){
//Target class
Object target = new UserServiceImpl();
//Transaction class
MyTransaction transaction = new MyTransaction();
ObjectInterceptor proxyObject = new ObjectInterceptor(target, transaction);
/**
* The meaning of the three parameters:
* 1. The class loader of the target class
* 2. All the implemented interfaces of the target class
* 3. Interceptor
*/
UserService userService = (UserService) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), proxyObject);
userService.addUser(null);
}

Adding business methods to UserService later will automatically generate proxy objects for us without changing the code. And it is also possible to replace UserService with another class.

  That is to say, the proxy object can proxy multiple target classes and multiple target methods.

  Note: We are using JDK dynamic proxy here, and the requirement is that the interface must be implemented. Corresponding to another dynamic proxy implementation mode Cglib, it is not needed, we will not explain the implementation of cglib here.

AOP key terms

1.target: target class, the class that needs to be proxied. For example: UserService

  2. Joinpoint (connection point): The so-called connection point refers to those methods that may be intercepted. For example: all methods

  3. PointCut: A connection point that has been enhanced. For example: addUser()

  4. Advice notification/enhancement, enhanced code. For example: after, before

  5. Weaving: refers to the process of applying enhanced advice to the target object to create a new proxy object proxy.

  6.proxy proxy class: notification + entry point

  7. Aspect: It is a combination of pointcut and advice

  It can be understood according to the following picture:

Image for question

AOP notification types  

  Spring can be divided into 5 categories according to the position of the connection point of the notification advice in the target class method

  • Advance notice org.springframework.aop.MethodBeforeAdvice
  • Implement enhancements before the target method is executed, such as the before() method in the above example
  • Post notification org.springframework.aop.AfterReturningAdvice
  • Implement enhancements after the target method is executed, such as the after() method in the above example
  • Surround notification org.aopalliance.intercept.MethodInterceptor
  • Implement enhancements before and after target method execution
  • Exception thrown notification org.springframework.aop.ThrowsAdvice
  • Implement enhancements after the method throws an exception
  • Introduction notice org.springframework.aop.IntroductionInterceptor

Add some new methods and properties to the target class

We only need to configure the following in Spring's configuration file applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--1, create target class -->
<bean id="userService" class="com.my.aop.UserServiceImpl"></bean>
<!--2, create an aspect class (notice) -->
<bean id="transaction" class="com.my.aop.one.MyTransaction"></bean>

<!--3, aop programming
3.1 Import namespace
3.2 Use <aop:config> to configure
proxy-target-class="true" uses cglib proxy when declared
If not declared, Spring will automatically choose cglib proxy or JDK dynamic proxy
<aop:pointcut> Entry point, get specific methods from the target
<aop:advisor> Special aspect, only one notification and one entry point
advice-ref advice reference
pointcut-ref pointcut reference
3.3 Pointcut expression
execution(* com.my.aop.*.*(..))
Selection method Any return value Any package Class name Any method name Any parameter

-->
<aop:config>
<!-- Pointcut expression -->
<aop:pointcut expression="execution(* com.my.aop.*.*(..))" id="myPointCut"/>
<aop:aspect ref="transaction">
<!-- Configure the pre-notification, note that the value of method should be the same as the name of the class method of the corresponding aspect -->
<aop:before method="before" pointcut-ref="myPointCut"></aop:before>
<aop:after-returning method="after" pointcut-ref="myPointCut"/>
</aop:aspect>
</aop:config>
</beans>

@Test
public void testAop(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService useService = (UserService) context.getBean("userService");
useService.addUser(null);
}

①The entry point expression, a complete method is expressed as follows:

execution (modifiers-pattern? ref-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
Class modifier; Return value; package of method; Method name; The exception

Then according to the above comparison, we can understand very well:

execution(* com.my.aop.*.*(..))
Select method; Any return value; package; any Class name; Any method name; Any parameter;

Then it means that the return value is arbitrary, the package name is any method name in any class name under com.ys.aop, and the parameters are arbitrary.

What if the pointcut expression has multiple different directories?

<aop:pointcut expression="execution(* com.my.*Service1.*(..)) ||
execution(* com.my.*Service2.*(..))" id="myPointCut"/>

It means to match any method of the class ending with Service1 or Service2 under the com.my package.

AOP pointcut expressions support multiple forms of definition rules:

1. Execution: execution of matching method (commonly used)
execution(public *.*(..))
2.within: match the method in the package or sub-package
within(com.my.aop..*)
3.this: match the method in the proxy object that implements the interface
this(com.my.aop.user.UserDAO)
4.target: Match the method in the target object that implements the interface
target(com.my.aop.user.UserDAO)
5.args: The method of matching parameter format in accordance with the standard
args(int,int)
6.bean(id) methods to the specified bean
bean('userServiceId')

② The specific loading steps of springAOP:

  1. When the spring container starts, the spring configuration file is loaded

  2. Create objects for all beans in the configuration file

  3. The spring container will parse the configuration of aop:config

Analyze the pointcut expression and use the pointcut expression to match the bean included in the spring container

If the match is successful, a proxy object will be created for the bean, and the method of the proxy object = target method + notification

If the match is unsuccessful, no proxy object will be created

  4. When the client uses context.getBean() to obtain an object, if the object has a proxy object, the proxy object is returned; if not, the target object is returned

  Note: If the target class does not implement the interface, the spring container will use cglib to generate proxy objects, if the interface is implemented, it will use jdk.

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

public class StudentServiceAspect {

public void doBefore(JoinPoint jp){
System.out.println("Class name:"+jp.getTarget().getClass().getName());
System.out.println("Method name:"+jp.getSignature().getName());
System.out.println("Start adding student:"+jp.getArgs()[0]);
}
To
public void doAfter(JoinPoint jp){
System.out.println("Class name:"+jp.getTarget().getClass().getName());
System.out.println("Method name:"+jp.getSignature().getName());
System.out.println("Student addition completed:"+jp.getArgs()[0]);
}
To
public Object doAround(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("Before adding student");
Object retVal=pjp.proceed();
System.out.println(retVal);
System.out.println("After adding student");
return retVal;
}
To
public void doAfterReturning(JoinPoint jp){
System.out.println("Return notification");
}
To
public void doAfterThrowing(JoinPoint jp,Throwable ex){
System.out.println("Exception Notification");
System.out.println("Exception information:"+ex.getMessage());
}
}

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">

<bean id="studentServiceAspect" class="com.java.advice.StudentServiceAspect"></bean>

<bean id="studentService" class="com.java.service.impl.StudentServiceImpl"></bean>

<aop:config>
<aop:aspect id="studentServiceAspect" ref="studentServiceAspect">
<aop:pointcut expression="execution(* com.java.service.*.*(..))" id="businessService"/>
<aop:before method="doBefore" pointcut-ref="businessService"/>
<aop:after method="doAfter" pointcut-ref="businessService"/>
<aop:around method="doAround" pointcut-ref="businessService"/>
<aop:after-returning method="doAfterReturning" pointcut-ref="businessService"/>
<aop:after-throwing method="doAfterThrowing" pointcut-ref="businessService" throwing="ex"/>
</aop:aspect>
</aop:config>
</beans>

public class StudentServiceImpl implements StudentService{

@Override
public void addStudent(String name) {
// System.out.println("Start adding student"+name);
System.out.println("Add student"+name);
System.out.println(1/0);
// System.out.println("Complete the addition of students"+name+"");
}

}

OUTPUT

Method name:addStudent

Start adding student

Add student Joe

Before adding student

Add student Joe

Return notification

null

After adding student

AspectJ is an aspect-oriented framework that extends the Java language.

Aspect notification type defines the type name and method format. The types are as follows:

before: pre-notification (application: various verification)
Execute before the method is executed, if the notification throws an exception, prevent the method from running
afterReturning: Post notification (application: regular data processing)
The method is executed after the normal return, if an exception is thrown in the method, the notification cannot be executed
It must be executed after the method is executed, so the return value of the method can be obtained.
around: around notifications (application: very powerful, can do anything)
The method is executed before and after execution, which can prevent the execution of the method
The target method must be executed manually
afterThrowing: throw exception notification (application: wrap exception information)
The method is executed after throwing an exception, if the method does not throw an exception, it cannot be executed
after: final notice (application: cleaning up the scene)
Execute after the method is executed, regardless of whether there is an exception in the method

The most important thing here is the around notice, which can replace any notice above.

The meaning expressed in the program is as follows:

try{
//before
//Manually execute the target method
//afterRetruning
} catch(){
//afterThrowing
} finally{
//after
}

AOP specific examples

public interface UserService {
public void addUser();
public void deleteUser();
}

Create an implementation class

public class UserServiceImpl implements UserService{
@Override
public void addUser() {
System.out.println("Add User");
}
@Override
public void deleteUser() {
System.out.println("Delete User");
}
}

Create aspect classes (including various notifications)

import org.aspectj.lang.JoinPoint;


public class MyAspect {
/**
* JoinPoint can get some basic information about the target method
* @param joinPoint
*/
public void myBefore(JoinPoint joinPoint){
System.out.println("Pre-notification: "+ joinPoint.getSignature().getName());
}

public void myAfterReturning(JoinPoint joinPoint,Object ret){
System.out.println("Post notification: "+ joinPoint.getSignature().getName() +", -->" + ret);
}

public void myAfter(){
System.out.println("Final Notice");
}

}

Create spring configuration file applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--1, create target class -->
<bean id="userService" class="com.my.aop.UserServiceImpl"></bean>
<!--2, create an aspect class (notice) -->
<bean id="myAspect" class="com.my.aop.MyAspect"></bean>

<!--3, aop programming
3.1 Import namespace
3.2 Use <aop:config> to configure
proxy-target-class="true" uses cglib proxy when declared
If not declared, Spring will automatically choose cglib proxy or JDK dynamic proxy
<aop:pointcut> Entry point, get specific methods from the target
<aop:advisor> Special aspect, only one notification and one entry point
advice-ref advice reference
pointcut-ref pointcut reference
3.3 Pointcut expression
execution(* com.my.aop.*.*(..))
Selection method Any return value Any package Class name Any method name Any parameter

-->
<aop:config>
<aop:aspect ref="myAspect">
<!-- Pointcut expression -->
<aop:pointcut expression="execution(* com.my.aop.*.*(..))" id="myPointCut"/>
<!-- 3.1 Pre-notification
<aop:before method="" pointcut="" pointcut-ref=""/>
method: notification, and method name
pointcut: Pointcut expression, this expression can only be used in the current notification.
pointcut-ref: Pointcut reference, which can share pointcuts with other notifications.
Notification method format: public void myBefore(JoinPoint joinPoint){
Parameter 1: org.aspectj.lang.JoinPoint is used to describe the connection point (target method), obtain the target method name, etc.
-->
<aop:before method="myBefore" pointcut-ref="myPointCut"/>


<!-- 3.2 Post notification, execute after the target method, get the return value
<aop:after-returning method="" pointcut-ref="" returning=""/>
The name of the second parameter of the returning notification method
Notification method format: public void myAfterReturning(JoinPoint joinPoint,Object ret){
Parameter 1: Connection point description
Parameter 2: Type Object, parameter name returning="ret" configured
-->
<aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="ret" />

<!-- 3.3 Final notice -->
<aop:after method="myAfter" pointcut-ref="myPointCut"/>

</aop:aspect>
</aop:config>
</beans>

@Test
public void testAop(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService useService = (UserService) context.getBean("userService");
useService.addUser();
}

Test exception notification

public void addUser() {
int i = 1/0;//Obviously it will throw that the divisor cannot be 0
System.out.println("Add User");
}

Noodles

public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
System.out.println("Throwing exception notification: "+ e.getMessage());
}

<!-- 3.4 Throw an exception
<aop:after-throwing method="" pointcut-ref="" throwing=""/>
throwing: the name of the second parameter of the notification method
Notification method format: public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
Parameter 1: Connection point description object
Parameter 2: Get exception information, type Throwable, parameter name is configured by throwing="e"
-->
<aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e"/>

@Test
public void testAop(){
String str = "com/my/execption/applicationContext.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(str);
UserService useService = (UserService) context.getBean("userService");
useService.addUser();
}

Test surround notification

public class MyAspect {

public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("Pre-notification");
//Manually execute the target method
Object obj = joinPoint.proceed();

System.out.println("Post notification");
return obj;
}

}

The applicationContext.xml configuration is as follows:

Through xml configuration.

<!-- Surround notification
<aop:around method="" pointcut-ref=""/>
Notification method format: public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
Return value type: Object
Method name: any
Parameters: org.aspectj.lang.ProceedingJoinPoint
Throw an exception
Execution target method: Object obj = joinPoint.proceed();
-->
<aop:around method="myAround" pointcut-ref="myPointCut"/>

@Test
public void testAop(){
String str = "com/my/around/applicationContext.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(str);
UserService useService = (UserService) context.getBean("userService");
useService.addUser();
}

Annotation to achieve AOP

 @Aspect declares the aspect, modifies the aspect class, and gets notified.

  Notice

    @Before

    @AfterReturning after

    @Around surround

    @AfterThrowing throws an exception

    @After finally

  Entry point

    @PointCut, after modifying the method private void xxx(){}, get the pointcut reference through the "method name"

Import the corresponding namespace in 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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">

</beans>

Annotation configuration bean

 xml configuration:

<!--1, create a target class -->
<bean id="userService" class="com.my.aop.UserServiceImpl"></bean>
<!--2, create an aspect class (notice) -->
<bean id="myAspect" class="com.my.aop.MyAspect"></bean>

Image for question

Configure scan annotation recognition

Add the following configuration in the applicationContext.xml file:

<!-- Configure scan annotation class
base-package: indicates the package name containing the annotation class.
If you scan multiple packages, write the following code in multiple lines and change the content in base-package!
-->
<context:component-scan base-package="com.my.aop"></context:component-scan>

Add @Aspect annotation to the aspect class as follows:

Tell Spring which is the aspect class

Image for question

How to make Spring recognize the AOP annotations we configured

  We add the following configuration to the applicationContext.xml file:

<!--2, make sure the aop annotation takes effect -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

Annotation configuration pre-notification

  We first look at the xml configuration pre-notification as follows:

<!-- Pointcut expression -->
<aop:pointcut expression="execution(* com.my.aop.*.*(..))" id="myPointCut"/>
<!-- 3.1 Pre-notification
<aop:before method="" pointcut="" pointcut-ref=""/>
method: notification, and method name
pointcut: Pointcut expression, this expression can only be used in the current notification.
pointcut-ref: Pointcut reference, which can share pointcuts with other notifications.
Notification method format: public void myBefore(JoinPoint joinPoint){
Parameter 1: org.aspectj.lang.JoinPoint is used to describe the connection point (target method), obtain the target method name, etc.
-->
<aop:before method="myBefore" pointcut-ref="myPointCut"/>

Then the way of annotation is as follows:

Image for question

Annotation configuration post notification

xml configuration post notification:

<!-- 3.2 Post notification, execute after the target method, get the return value
<aop:after-returning method="" pointcut-ref="" returning=""/>
The name of the second parameter of the returning notification method
Notification method format: public void myAfterReturning(JoinPoint joinPoint,Object ret){
Parameter 1: Connection point description
Parameter 2: Type Object, parameter name returning="ret" configured
-->
<aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="ret" />

Note that the post notification has a returning="ret" configuration, which is used to obtain the return value of the target method.

Transaction generally refers to something to be done or done. In computer terms, it refers to a program execution unit (unit) that accesses and may update various data items in the database.

  Here we explain with an example of withdrawing money: For example, if you go to an ATM to withdraw 1,000 dollars, there are roughly two steps: the first step is to enter the password amount, and the bank card deducts 1,000 dollars; the second step is 1,000 dollars from the ATM . Both of these steps must be executed or neither. If the bank card deducts 1,000 dollars but the ATM fails to pay, you will lose 1,000 dollars; if the bank card deduction fails but the ATM pays 1,000 dollars, then the bank will lose 1,000 dollars.

  How to ensure that one of these two steps will not be abnormal while the other is executed successfully? Affairs is used to solve such problems. A transaction is a series of actions. They are integrated together to be a complete unit of work. These actions must all be completed. If one fails, the transaction will roll back to the initial state, as if nothing happened. . In enterprise-level application development, transaction management is an essential technology to ensure data integrity and consistency.

Four characteristics of transactions (ACID)

  ① Atomicity: A transaction is an atomic operation and consists of a series of actions. The atomicity of the transaction ensures that the actions are either all completed or completely ineffective.

  ② Consistency: Once the transaction is completed (regardless of success or failure), the system must ensure that the business modeled by it is in a consistent state, rather than partially completed and partially failed. Data in reality should not be destroyed.

  ③ Isolation (Isolation): There may be many transactions that process the same data at the same time, so each transaction should be isolated from other transactions to prevent data corruption.

  ④ Durability: Once the transaction is completed, no matter what system error occurs, its result should not be affected, so that it can recover from any system crash. Normally, the result of the transaction is written to persistent storage.

PlatformTransactionManager transaction manager

 The interface of Spring transaction manager is org.springframework.transaction.PlatformTransactionManager. Spring does not directly manage transactions. Through this interface, Spring provides corresponding transaction managers for various platforms such as JDBC, Hibernate, etc. Responsibilities are delegated to the affairs of the relevant platform framework provided by persistence mechanisms such as Hibernate or JTA.

That is to say, Spring transaction management provides a consistent programming model for different transaction APIs, and the specific transaction management mechanism is implemented by each platform.

AccountDao interface:

public interface AccountDao {
/**
* money transfer
* @param outer remitter
* @param money remittance amount
*/
public void out(String outer,int money);

/**
* Collection
* @param inner payee
* @param money collection amount
*/
public void in(String inner,int money);

import org.springframework.jdbc.core.support.JdbcDaoSupport;

import com.my.dao.AccountDao;

public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {

/**
* Decrease the account amount according to the user name
*/
@Override
public void out(String outer, int money) {
this.getJdbcTemplate().update("update account set money = money-? where username = ?",money,outer);
}

/**
* Increase account amount based on user name
*/
@Override
public void in(String inner, int money) {
this.getJdbcTemplate().update("update account set money = money +? where username = ?",money,inner);
}

}

public interface AccountService {

/**
* Transfer
* @param outer remitter
* @param inner payee
* @param money transaction amount
*/
public void transfer(String outer,String inner,int money);

}

public class AccountServiceImpl implements AccountService{

private AccountDao accountDao;

public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public void transfer(String outer, String inner, int money) {
accountDao.out(outer, money);
accountDao.in(inner, money);
}

}

<?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"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>

<bean id="accountDao" class="com.my.dao.impl.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>

<bean id="accountService" class="com.my.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>
</beans>

public class TransactionTest {

@Test
public void testNoTransaction(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
AccountService account = (AccountService) context.getBean("accountService");
//Tom transfer 1000 to Marry
account.transfer("Tom", "Marry", 1000);
}

}

Programmatic transaction processing : The so-called programmatic transaction refers to the realization of the transaction by coding, allowing users to precisely define the boundary of the transaction in the code. That is similar to JDBC programming to achieve transaction management. Management uses TransactionTemplate or directly uses the underlying PlatformTransactionManager. For programmatic transaction management, Spring recommends using TransactionTemplate.

Declarative transaction processing : Management is based on AOP. Its essence is to intercept before and after the method, then create or add a transaction before the target method starts, and submit or roll back the transaction according to the execution after the target method is executed. The biggest advantage of declarative transactions is that they do not need to be managed by programming, so there is no need to dope transaction management code in the business logic code. You only need to make relevant transaction rule declarations in the configuration file (or through @Transactional Annotation), you can apply transaction rules to business logic.

  Simply put, programmatic transactions invade the business code, but provide more detailed transaction management; and declarative transactions, based on AOP, can not only play a role in transaction management, but also do not affect the specific implementation of the business code.

Programmatic transaction processing to realize transfer (TransactionTemplate)

We inject the TransactionTemplate template in the Service layer. Because the template is used to manage transactions, the template needs to be injected into the transaction manager DataSourceTransactionManager. The transaction manager is still managed by the underlying JDBC after all, so we need to inject the DataSource into the transaction manager. These steps are as follows:

AccountServiceImpl interface:

import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import com.my.dao.AccountDao;
import com.my.service.AccountService;

public class AccountServiceImpl implements AccountService{

private AccountDao accountDao;
private TransactionTemplate transactionTemplate;

public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public void transfer(final String outer,final String inner,final int money) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus arg0) {
accountDao.out(outer, money);
//int i = 1/0;
accountDao.in(inner, money);
}
});
}

}

Spring global configuration file applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>

<bean id="accountDao" class="com.my.dao.impl.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>

<bean id="accountService" class="com.my.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
<property name="transactionTemplate" ref="transactionTemplate"></property>
</bean>

<!-- Create template -->
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="txManager"></property>
</bean>

<!-- Configure the transaction manager, the manager needs transactions, the transaction is obtained from Connection, and the connection is obtained from the connection pool DataSource -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>

The underlying PlatformTransactionManager for transaction management

//Define a TransactionManager of a certain framework platform, such as JDBC, Hibernate
DataSourceTransactionManager dataSourceTransactionManager =
new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(this.getJdbcTemplate().getDataSource()); // Set the data source

DefaultTransactionDefinition transDef = new DefaultTransactionDefinition(); // Define transaction attributes
transDef.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED); // Set the propagation behavior property
TransactionStatus status = dataSourceTransactionManager.getTransaction(transDef); // Get transaction status
try {
// Database operation
accountDao.out(outer, money);
int i = 1/0;
accountDao.in(inner, money);

dataSourceTransactionManager.commit(status);// Submit
} catch (Exception e) {
dataSourceTransactionManager.rollback(status);// rollback
}

Declarative transaction processing to realize transfer (based on AOP xml configuration)

The Dao layer and the Service layer remain unchanged from the transaction we started with to realize transfers. Mainly the applicationContext.xml file has changed.

  We configure aop to automatically generate a proxy in the applicationContext.xml file for transaction management:

  ①configuration manager

  ②configuration transaction details

  ③configure aop

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

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>

<bean id="accountDao" class="com.my.dao.impl.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>

<bean id="accountService" class="com.my.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>

<!-- 1 Transaction Manager -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>

<!-- 2 Transaction details (transaction notification), based on aop screening, for example, determine what kind of transaction to use for the three ABCs. For example: AC read-write, B read-only, etc.
<tx:attributes> is used to configure transaction details (attributes)
<tx:method name=""/> Details specific configuration
propagation behavior, REQUIRED: must; REQUIRES_NEW: must be new
isolation level
-->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="transfer" propagation="REQUIRED" isolation="DEFAULT"/>
<tx:method name="*"/>//All methods
</tx:attributes>
</tx:advice>

<!-- 3 AOP programming, using the entry point expression to determine the enhanced connector from the target class method to obtain the entry point -->
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.my.service..*.*(..))"/>//Configure thing notification
<aop:pointcut expression="execution(* com.my.service..*.*(..))" id="serviceMethod">//configuration pointcut
</aop:config>
</beans>

1. Propagation behavior: When a transaction method is called by another transaction method, you must specify how the transaction should be propagated.

  Spring defines the following seven propagation behaviors. Here is how to propagate transactions between A business and B business as an example:

  ①PROPAGATION_REQUIRED: required, required. By default, if A has a transaction, B will use that transaction; if A has no transaction, B will create a new transaction.

  ②PROPAGATION_SUPPORTS: supports, support. If A has a transaction, B will use that transaction; if A has no transaction, B will execute as a non-transactional.

  ③PROPAGATION_MANDATORY: mandatory, mandatory. If A has a transaction, B will use that transaction; if A has no transaction, B will throw an exception.

  ④PROPAGATION_REQUIRES_NEW: requires_new, must be new. If A has a transaction, suspend A’s transaction and B creates a new transaction; if A has no transaction, B creates a new transaction.

  ⑤PROPAGATION_NOT_SUPPORTED: not_supported, not supported. If A has a transaction, suspend A's transaction and B will be executed as a non-transactional; if A has no transaction, B will be executed as a non-transactional.

  ⑥PROPAGATION_NEVER: never, never. If A has a transaction, B will throw an exception; if A has no transaction, B will execute as a non-transactional.

  ⑦PROPAGATION_NESTED : nested, nested. The bottom layer of A and B uses a savepoint mechanism to form nested transactions.

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

<!-- Configure transaction notification -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="edit*" propagation="REQUIRED" />
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="new*" propagation="REQUIRED" />
<tx:method name="set*" propagation="REQUIRED" />
<tx:method name="remove*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="change*" propagation="REQUIRED" />
<tx:method name="get*" propagation="REQUIRED" read-only="true" />
<tx:method name="find*" propagation="REQUIRED" read-only="true" />
<tx:method name="load*" propagation="REQUIRED" read-only="true" />
<tx:method name="*" propagation="REQUIRED" read-only="true" />
</tx:attributes>
</tx:advice>

<!-- Configuration transaction aspect -->
<aop:config>
<!-- Configuration cut point -->
<aop:pointcut id="serviceMethod" expression="execution(* com.java1234.service.*.*(..))" />
<!-- Configure transaction notification -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod"/>
</aop:config>

2. Isolation level: defines the degree to which a transaction may be affected by other concurrent transactions.

  Problems caused by concurrent transactions:

  In a typical application, multiple transactions run concurrently, often operating the same data to complete their tasks. Although concurrency is necessary, it may cause the following problems.

    ① Dirty reads-Dirty reads occur when one transaction reads data that has been rewritten by another transaction but has not yet been committed. If the rewrite is rolled back later, the data obtained by the first transaction is invalid.

    ② Nonrepeatable read-nonrepeatable read occurs when a transaction executes the same query twice or more, but each time it gets different data. This is usually because another concurrent transaction was updated during the two queries.

    ③ Phantom read-Phantom read is similar to non-repeatable read. It occurs when a transaction (T1) reads a few rows of data, and then another concurrent transaction (T2) inserts some data. In subsequent queries, the first transaction (T1) will find that there are more records that did not exist.

Note: The focus of non-repeatable reading is modification, while the focus of phantom reading is adding or deleting.

 In Spring transaction management, the following isolation levels are defined for us:

  ① ISOLATION_DEFAULT: Use the default isolation level of the back-end database

  ② ISOLATION_READ_UNCOMMITTED: the lowest isolation level, allowing to read data changes that have not yet been committed, which may cause dirty reads, phantom reads or non-repeatable reads

  ③ ISOLATION_READ_COMMITTED: Allows to read the data submitted by concurrent transactions, which can prevent dirty reads, but phantom reads or non-repeatable reads may still occur

  ④ ISOLATION_REPEATABLE_READ: The results of multiple reads of the same field are consistent, unless the data is modified by the transaction itself, which can prevent dirty reads and non-repeatable reads, but phantom reads may still occur

  ⑤ ISOLATION_SERIALIZABLE: The highest isolation level, fully compliant with the ACID isolation level, to ensure that dirty reads, non-repeatable reads, and phantom reads are prevented, and it is also the slowest transaction isolation level, because it is usually achieved by completely locking transaction-related database tables of

  The isolation levels defined above are also represented by constants -1,0,1,2,4,8 in Spring's TransactionDefinition.class.

3.read only

  This is the third characteristic of the transaction, whether it is a read-only transaction. If the transaction only performs this operation on the back-end database, the database can use the read-only feature of the transaction to perform some specific optimizations. By setting the transaction as read-only, you can give the database a chance to apply the optimization measures it thinks are appropriate.

  4.transaction timeout

  In order for the application to run well, the transaction cannot run for too long. Because transactions may involve locks on the back-end database, long-term transactions will unnecessarily occupy database resources. Transaction timeout is a timer of the transaction. If the transaction is not completed within a certain period of time, it will automatically roll back instead of waiting for its end.

  5.rollback rules

  The last aspect of the transaction pentagon is a set of rules that define which exceptions will cause the transaction to roll back and which will not. By default, the transaction will only roll back when it encounters a runtime exception, and will not roll back when it encounters a checked exception (this behavior is consistent with the rollback behavior of EJB). But you can declare that the transaction rolls back as it encounters a runtime exception when it encounters a specific checked exception. Similarly, you can also declare that the transaction will not roll back when encountering specific exceptions, even if these exceptions are runtime exceptions.

Declarative transaction processing realizes transfer (based on AOP annotation configuration) 

Divided into the following two steps:

  ① Configure the transaction manager in applicationContext.xml, and hand it over to spring

  ② Add annotations to the target class or target method @Transactional

  First configure the following in the applicationContext.xml file:

<!-- 1 Transaction Manager -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 2 Hand over the manager to spring
* transaction-manager configuration transaction manager
* proxy-target-class
true: the underlying cglib proxy is mandatory
-->
<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>

Secondly, add annotation @Transactional to the target class or method. If you add it to the class, it means that all methods in the class add a transaction. If you add it to a method, only that method has a transaction.

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.my.dao.AccountDao;
import com.my.service.AccountService;

@Transactional(propagation=Propagation.REQUIRED , isolation = Isolation.DEFAULT)
@Service("accountService")
public class AccountServiceImpl implements AccountService{
@Resource(name="accountDao")
private AccountDao accountDao;

public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public void transfer(String outer, String inner, int money) {
accountDao.out(outer, money);
//int i = 1/0;
accountDao.in(inner, money);
}

}

Spring support for jdbc

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

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>

<context:property-placeholder location="jdbc.properties"/>

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>


<bean id="studentDao" class="com.java1234.dao.impl.StudentDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>

<bean id="studentService" class="com.java1234.service.impl.StudentServiceImpl">
<property name="studentDao" ref="studentDao"></property>
</bean>

</beans>

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db_spring
jdbc.username=root
jdbc.password=123456

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCallbackHandler;


public class StudentDaoImpl implements StudentDao{

private JdbcTemplate jdbcTemplate;

public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}

@Override
public int addStudent(Student student) {
String sql="insert into t_student values(null,?,?)";
Object []params=new Object[]{student.getName(),student.getAge()};
return jdbcTemplate.update(sql,params);
}

@Override
public int updateStudent(Student student) {
String sql="update t_student set name=?,age=? where id=?";
Object []params=new Object[]{student.getName(),student.getAge(),student.getId()};
return jdbcTemplate.update(sql,params);
}

@Override
public int deleteStudent(int id) {
String sql="delete from t_student where id=?";
Object []params=new Object[]{id};
return jdbcTemplate.update(sql,params);
}

@Override
public List<Student> findStudents() {
String sql="select * from t_student";
final List<Student> studentList=new ArrayList<Student>();
jdbcTemplate.query(sql, new RowCallbackHandler(){

@Override
public void processRow(ResultSet rs) throws SQLException {
Student student=new Student();
student.setId(rs.getInt("id"));
student.setName(rs.getString("name"));
student.setAge(rs.getInt("age"));
studentList.add(student);
}

});
return studentList;
}

}

import java.util.List;

public class StudentServiceImpl implements StudentService{

private StudentDao studentDao;

public void setStudentDao(StudentDao studentDao) {
this.studentDao = studentDao;
}

@Override
public int addStudent(Student student) {
return studentDao.addStudent(student);
}

@Override
public int updateStudent(Student student) {
return studentDao.updateStudent(student);
}

@Override
public int deleteStudent(int id) {
return studentDao.deleteStudent(id);
}

@Override
public List<Student> findStudents() {
return studentDao.findStudents();
}

import java.util.List;

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class T {

private ApplicationContext ac;

@Before
public void setUp() throws Exception {
ac=new ClassPathXmlApplicationContext("beans.xml");
}

@Test
public void addStudent() {
StudentService studentService=(StudentService)ac.getBean("studentService");
int addNums=studentService.addStudent(new Student("Joe", 1));
if(addNums==1){
System.out.println("Added successfully");
}
}
To
@Test
public void updateStudent() {
StudentService studentService=(StudentService)ac.getBean("studentService");
int updateNums=studentService.updateStudent(new Student(8,"Joe2", 2));
if(updateNums==1){
System.out.println("Updated successfully");
}
}
To
@Test
public void deleteStudent() {
StudentService studentService=(StudentService)ac.getBean("studentService");
int deleteNums=studentService.deleteStudent(8);
if(deleteNums==1){
System.out.println("Delete successfully");
}
}
To
@Test
public void findStudents() {
StudentService studentService=(StudentService)ac.getBean("studentService");
List<Student> studentList=studentService.findStudents();
for(Student student:studentList){
System.out.println(student);
}
}

}

Support named parameter variables

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

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>

<context:property-placeholder location="jdbc.properties"/>

<bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="dataSource"></constructor-arg>
</bean>


<bean id="studentDao" class="com.java.dao.impl.StudentDaoImpl">
<property name="namedParameterJdbcTemplate" ref="namedParameterJdbcTemplate"></property>
</bean>

<bean id="studentService" class="com.java.service.impl.StudentServiceImpl">
<property name="studentDao" ref="studentDao"></property>
</bean>

</beans>

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

public class StudentDaoImpl implements StudentDao{

private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

public void setNamedParameterJdbcTemplate(
NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
}

@Override
public int addStudent(Student student) {
String sql="insert into t_student values(null,:name,:age)";
MapSqlParameterSource sps=new MapSqlParameterSource();
sps.addValue("name", student.getName());
sps.addValue("age", student.getAge());
return namedParameterJdbcTemplate.update(sql,sps);
}

@Override
public int updateStudent(Student student) {
String sql="update t_student set name=:name,age=:age where id=:id";
MapSqlParameterSource sps=new MapSqlParameterSource();
sps.addValue("name", student.getName());
sps.addValue("age", student.getAge());
sps.addValue("id", student.getId());
return namedParameterJdbcTemplate.update(sql,sps);
}

@Override
public int deleteStudent(int id) {
String sql="delete from t_student where id=:id";
MapSqlParameterSource sps=new MapSqlParameterSource();
sps.addValue("id", id);
return namedParameterJdbcTemplate.update(sql,sps);
}

@Override
public List<Student> findStudents() {
String sql="select * from t_student";
final List<Student> studentList=new ArrayList<Student>();
namedParameterJdbcTemplate.query(sql, new RowCallbackHandler(){

@Override
public void processRow(ResultSet rs) throws SQLException {
Student student=new Student();
student.setId(rs.getInt("id"));
student.setName(rs.getString("name"));
student.setAge(rs.getInt("age"));
studentList.add(student);
}

});
return studentList;
}

}

import java.util.List;

public class StudentServiceImpl implements StudentService{

private StudentDao studentDao;

public void setStudentDao(StudentDao studentDao) {
this.studentDao = studentDao;
}

@Override
public int addStudent(Student student) {
return studentDao.addStudent(student);
}

@Override
public int updateStudent(Student student) {
return studentDao.updateStudent(student);
}

@Override
public int deleteStudent(int id) {
return studentDao.deleteStudent(id);
}

@Override
public List<Student> findStudents() {
return studentDao.findStudents();
}
}

Spring integrates hibernate

web,xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http ://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>S2SH</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

<!-- Add support for spring -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>

<!-- Define Spring listener, load Spring -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- Add support for struts2 -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- Session delay loading to the page -->
<filter>
<filter-name>openSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>singleSession</param-name>
<param-value>true</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>openSessionInViewFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
</web-app>

struts.xml

<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>
<constant name="struts.action.extension" value="action" />

<package name="s2sh" namespace="/user" extends="struts-default">
<action name="user_*" method="{1}" class="com.java.action.UserAction">
<result name="success">/success.jsp</result>
<result name="error">/index.jsp</result>
</action>
</package>

</struts>

hibernate.cfg.xml

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
To
<!-- Dialect-->
<property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>

<!-- Display sql statement -->
<property name="show_sql">true</property>

<!-- Automatic update -->
<property name="hbm2ddl.auto">update</property>


</session-factory>
</hibernate-configuration>

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

<!-- Define data source -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"
value="com.mysql.jdbc.Driver">
</property>
<property name="url"
value="jdbc:mysql://localhost:3306/test">
</property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
</bean>

<!-- session factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="configLocation" value="classpath:hibernate.cfg.xml"/>
<!-- Automatically scan hibernate class files configured in annotation mode -->
<property name="packagesToScan">
<list>
<value>com.java.entity</value> //All classes under the package will be scanned
</list>
</property>
</bean>

<!-- Configure Transaction Manager -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>

<!-- Configure transaction notification properties -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- Define transaction propagation attributes -->
<tx:attributes>
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="edit*" propagation="REQUIRED" />
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="new*" propagation="REQUIRED" />
<tx:method name="set*" propagation="REQUIRED" />
<tx:method name="remove*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="change*" propagation="REQUIRED" />
<tx:method name="get*" propagation="REQUIRED" read-only="true" />
<tx:method name="find*" propagation="REQUIRED" read-only="true" />
<tx:method name="load*" propagation="REQUIRED" read-only="true" />
<tx:method name="*" propagation="REQUIRED" read-only="true" />
</tx:attributes>
</tx:advice>


<!-- Configuration transaction aspect -->
<aop:config>
<aop:pointcut id="serviceOperation"
expression="execution(* com.java.service..*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation" />
</aop:config>

<!-- Automatically load the build bean -->
<context:component-scan base-package="com.java" /> //All configured classes are annotated

</beans>

entity

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(name="t_user")
public class User {

private Integer id;
private String userName;
private String password;


@Id
@GenericGenerator(name = "generator", strategy = "native")
@GeneratedValue(generator = "generator")
@Column(name = "id", length=11)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(name = "userName", length = 20)
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
@Column(name = "password", length = 20)
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}

}

import java.io.Serializable;
import java.util.List;

/**
* Basic database operations
*
*
*/
public interface BaseDao<T> {

/**
* Save an object
*
* @param o
* @return
*/
public Serializable save(T o);

/**
* Delete an object
*
* @param o
*/
public void delete(T o);

/**
* Update an object
*
* @param o
*/
public void update(T o);

/**
* Save or update objects
*
* @param o
*/
public void saveOrUpdate(T o);

/**
* Inquire
*
* @param hql
* @return
*/
public List<T> find(String hql);

/**
* Query collection
*
* @param hql
* @param param
* @return
*/
public List<T> find(String hql, Object[] param);

/**
* Query collection
*
* @param hql
* @param param
* @return
*/
public List<T> find(String hql, List<Object> param);

/**
* Query collection (with pagination)
*
* @param hql
* @param param
* @param page
* Check the page
* @param rows
* Display several records per page
* @return
*/
public List<T> find(String hql, Object[] param, Integer page, Integer rows);

/**
* Query collection (with pagination)
*
* @param hql
* @param param
* @param page
* @param rows
* @return
*/
public List<T> find(String hql, List<Object> param, Integer page, Integer rows);

/**
* Get an object
*
* @param c
* Object type
* @param id
* @return Object
*/
public T get(Class<T> c, Serializable id);

/**
* Get an object
*
* @param hql
* @param param
* @return Object
*/
public T get(String hql, Object[] param);

/**
* Get an object
*
* @param hql
* @param param
* @return
*/
public T get(String hql, List<Object> param);

/**
* select count(*) from class
*
* @param hql
* @return
*/
public Long count(String hql);

/**
* select count(*) from class
*
* @param hql
* @param param
* @return
*/
public Long count(String hql, Object[] param);

/**
* select count(*) from class
*
* @param hql
* @param param
* @return
*/
public Long count(String hql, List<Object> param);

/**
* Execute HQL statement
*
* @param hql
* @return number of responses
*/
public Integer executeHql(String hql);

/**
* Execute HQL statement
*
* @param hql
* @param param
* @return number of responses
*/
public Integer executeHql(String hql, Object[] param);

/**
* Execute HQL statement
*
* @param hql
* @param param
* @return
*/
public Integer executeHql(String hql, List<Object> param);

}

BaseDaOImpl.java

import java.io.Serializable;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository("baseDao")
@SuppressWarnings("all")
public class BaseDaOImpl<T> implements BaseDao<T> {

private SessionFactory sessionFactory;

public SessionFactory getSessionFactory() {
return sessionFactory;
}

@Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}

private Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}

public Serializable save(T o) {
return this.getCurrentSession().save(o);
}

public void delete(T o) {
this.getCurrentSession().delete(o);
}

public void update(T o) {
this.getCurrentSession().update(o);
}

public void saveOrUpdate(T o) {
this.getCurrentSession().saveOrUpdate(o);
}

public List<T> find(String hql) {
return this.getCurrentSession().createQuery(hql).list();
}

public List<T> find(String hql, Object[] param) {
Query q = this.getCurrentSession().createQuery(hql);
if (param != null && param.length > 0) {
for (int i = 0; i < param.length; i++) {
q.setParameter(i, param[i]);
}
}
return q.list();
}

public List<T> find(String hql, List<Object> param) {
Query q = this.getCurrentSession().createQuery(hql);
if (param != null && param.size() > 0) {
for (int i = 0; i < param.size(); i++) {
q.setParameter(i, param.get(i));
}
}
return q.list();
}

public List<T> find(String hql, Object[] param, Integer page, Integer rows) {
if (page == null || page < 1) {
page = 1;
}
if (rows == null || rows < 1) {
rows = 10;
}
Query q = this.getCurrentSession().createQuery(hql);
if (param != null && param.length > 0) {
for (int i = 0; i < param.length; i++) {
q.setParameter(i, param[i]);
}
}
return q.setFirstResult((page - 1) * rows).setMaxResults(rows).list();
}

public List<T> find(String hql, List<Object> param, Integer page, Integer rows) {
if (page == null || page < 1) {
page = 1;
}
if (rows == null || rows < 1) {
rows = 10;
}
Query q = this.getCurrentSession().createQuery(hql);
if (param != null && param.size() > 0) {
for (int i = 0; i < param.size(); i++) {
q.setParameter(i, param.get(i));
}
}
return q.setFirstResult((page - 1) * rows).setMaxResults(rows).list();
}

public T get(Class<T> c, Serializable id) {
return (T) this.getCurrentSession().get(c, id);
}

public T get(String hql, Object[] param) {
List<T> l = this.find(hql, param);
if (l != null && l.size() > 0) {
return l.get(0);
} else {
return null;
}
}

public T get(String hql, List<Object> param) {
List<T> l = this.find(hql, param);
if (l != null && l.size() > 0) {
return l.get(0);
} else {
return null;
}
}

public Long count(String hql) {
return (Long) this.getCurrentSession().createQuery(hql).uniqueResult();
}

public Long count(String hql, Object[] param) {
Query q = this.getCurrentSession().createQuery(hql);
if (param != null && param.length > 0) {
for (int i = 0; i < param.length; i++) {
q.setParameter(i, param[i]);
}
}
return (Long) q.uniqueResult();
}

public Long count(String hql, List<Object> param) {
Query q = this.getCurrentSession().createQuery(hql);
if (param != null && param.size() > 0) {
for (int i = 0; i < param.size(); i++) {
q.setParameter(i, param.get(i));
}
}
return (Long) q.uniqueResult();
}

public Integer executeHql(String hql) {
return this.getCurrentSession().createQuery(hql).executeUpdate();
}

public Integer executeHql(String hql, Object[] param) {
Query q = this.getCurrentSession().createQuery(hql);
if (param != null && param.length > 0) {
for (int i = 0; i < param.length; i++) {
q.setParameter(i, param[i]);
}
}
return q.executeUpdate();
}

public Integer executeHql(String hql, List<Object> param) {
Query q = this.getCurrentSession().createQuery(hql);
if (param != null && param.size() > 0) {
for (int i = 0; i < param.size(); i++) {
q.setParameter(i, param.get(i));
}
}
return q.executeUpdate();
}

}

public interface UserService {

public void saveUser(User user);

public void updateUser(User user);

public User findUserById(int id);

public void deleteUser(User user);

public List<User> findAllList();

public User findUserByNameAndPassword(User user);
}

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.java.dao.BaseDao;
import com.java.entity.User;
import com.java.service.UserService;

@Service("userService")
public class UserServiceImpl implements UserService{

@Resource
private BaseDao<User> baseDao;

@Override
public void saveUser(User user) {
// TODO Auto-generated method stub
baseDao.save(user);
}

@Override
public void updateUser(User user) {
// TODO Auto-generated method stub
baseDao.update(user);
}

@Override
public User findUserById(int id) {
return baseDao.get(User.class, id);
}

@Override
public void deleteUser(User user) {
baseDao.delete(user);
}

@Override
public List<User> findAllList() {
return baseDao.find("from User");
}

@Override
public User findUserByNameAndPassword(User user) {
return baseDao.get("from User u where u.userName=? and u.password=?", new Object[]{user.getUserName(),user.getPassword()});
}

}

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.struts2.interceptor.ServletRequestAware;
import org.springframework.stereotype.Controller;

import com.opensymphony.xwork2.ActionSupport;

@Controller
public class UserAction extends ActionSupport implements ServletRequestAware{

/**
*
*/
private static final long serialVersionUID = 1L;
To
private HttpServletRequest request;

@Resource
private UserService userService;
To
private User user;
private String error;
To
To
To
public User getUser() {
return user;
}



public void setUser(User user) {
this.user = user;
}



public String getError() {
return error;
}



public void setError(String error) {
this.error = error;
}


public String login()throws Exception{
HttpSession session=request.getSession();
User currentUser=userService.findUserByNameAndPassword(user);
if(currentUser!=null){
session.setAttribute("currentUser", currentUser);
return SUCCESS;
}else{
error="The username or password is wrong!";
return ERROR;
}
}

@Override
public void setServletRequest(HttpServletRequest request) {
// TODO Auto-generated method stub
this.request=request;
}

}

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/user/user_login.action" method="post">
userName:<input type="text" name="user.userName" value="${user.userName }"/><br/>
password:<input type="password" name="user.password" value="${user.password }"><br/>
<input type="submit" value="login"/><font color="red">${error }</font>
</form>
</body>
</html>

Spring framework construction

web,xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>prodatashow</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/spring*.xml</param-value>
</context-param>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet>
<servlet-name>AuthImg</servlet-name>
<servlet-class>com.platform.utils.AuthImg</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AuthImg</servlet-name>
<url-pattern>/authImage</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>/cusviews/index</welcome-file>
</welcome-file-list>
<error-page>
<error-code>404</error-code>
<location>/404Error</location>
</error-page>
</web-app>

spring-mvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">

<!-- Auto scan -->
<context:component-scan base-package="com.**.controller">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
</context:component-scan>

<!-- <mvc:annotation-driven /> -->

<!-- Start of static resources -->
<mvc:resources location="/404Error.html" mapping="/404Error.html"/>
<mvc:resources location="/view/**" mapping="/view/**"/>
<mvc:resources location="/application/**" mapping="/application/**"/>
<mvc:resources mapping="/platform/**" location="/platform/,classpath:/platform/" />
<mvc:resources mapping="/favicon.ico" location="/favicon.ico,classpath:/favicon.ico" />
<!-- End of static resources -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/" />
<mvc:exclude-mapping path="/login" />
<mvc:exclude-mapping path="/loginCheck" />
<mvc:exclude-mapping path="/view/**" />
<mvc:exclude-mapping path="/platform/**" />
<mvc:exclude-mapping path="/application/**" />
<bean class="com.interceptor.CusViewsInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
To
<!--Avoid downloading files when returning JSON when IE executes AJAX -->
<bean id="mappingJacksonHttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" value="#{jsonUtils.mapper}"/> <!-- Used for date output format conversion -->
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>*; charset=UTF-8</value>
</list>
</property>
</bean>
To
<!-- Custom intercept processing class -->
<bean id="cntenAccessInterceptor" class="com.platform.framework.web.interceptor.implAccessInterceptor"></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list>
<ref bean="cntenAccessInterceptor" />
</list>
</property>
</bean>
To
<!-- Start the annotation function of SpringMVC, complete the mapping of request and annotation POJO -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="mappingJacksonHttpMessageConverter" /> <!-- JSON converter -->
</list>
</property>
</bean>
To
<!-- jsp view resolution-->
<bean id="jspResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- My understanding of the configuration here is to automatically add a prefix and suffix to the string returned by the subsequent action method to become a usable URL address -->
<property name="contentType" value="text/html;charset=UTF-8"/>
<property name="prefix" value="/" />
<property name="suffix" value=".jsp" />
<property name="order" value="1"/>
</bean>
To
<!-- Configuration of freemarker -->
<bean id="freemarkerConfigurer" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPaths">
<list>
<value>/view</value>
</list>
</property>
<property name="defaultEncoding" value="UTF-8" />
<property name="freemarkerVariables">
<map>
<entry key="downSelector" value-ref="downSelectorDirective"/>
<entry key="checkBox" value-ref="checkBoxDirective"/>
<entry key="redioBox" value-ref="redioBoxDirective"/>
<entry key="popSelector" value-ref="popSelectorDirective"/>
<entry key="uploadPlugin" value-ref="uploadPluginDirective"/>
</map>
</property>
<property name="freemarkerSettings">
<props>
<prop key="template_update_delay">10</prop>
<prop key="locale">zh_CN</prop>
<prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop>
<prop key="date_format">yyyy-MM-dd</prop>
<prop key="number_format">#.##</prop>
</props>
</property>
</bean>
To
<bean id="freemarkerResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="cache" value="true" />
<property name="suffix" value=".html" />
<property name="order" value="

spring-common.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">

<!-- Import configuration file -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<!-- <property name="location" value="classpath*:config/*.properties" /> -->
<property name="locations">
<list>
<value>classpath:config/cache.properties</value>
<value>classpath:config/jdbc.properties</value>
<value>classpath:config/upload.properties</value>
</list>
</property>
</bean>

<!-- Date processing time class -->
<bean id="jsonUtils" class="com.platform.utils.JsonUtil" lazy-init="false"/>
To
<!-- Bean Manager -->
<bean id="springContextHolder" class="com.platform.framework.context.SpringContextHolder" lazy-init="false"/>
To
<!-- http session processing class -->
<bean id="httpSessionService" class="com.platform.framework.session.impl.HttpSessionService" lazy-init="false"/>
To
<!-- Cache processing class -->
<bean id="ehCacheManagerImpl" class="com.platform.framework.cache.impl.EhCacheManagerImpl" lazy-init="false"/>
<bean id="redisCacheManagerImpl" class="com.platform.framework.cache.impl.RedisCacheManagerImpl" lazy-init="false"/>
<bean id="cacheManager" class="net.sf.ehcache.CacheManager" lazy-init="false"/>
To
<!-- Spring and MyBatis integration, no need for mybatis configuration mapping file -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dynamicDataSource" />
<property name="databaseIdProvider" ref="databaseIdProvider" />
<property name="configLocation" value="classpath:config/mybatis-config.xml"></property>
<!-- Automatically scan the mapping.xml file -->
<property name="mapperLocations" value="classpath*:com/cnten/**/mapping/*.xml"></property>
</bean>
To
<!-- The name of the package where the DAO interface is located, Spring will automatically find the classes under it -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.**.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
To
<!-- Scan all Servcie classes -->
<context:component-scan base-package="com.**.service" />
<context:component-scan base-package="com.platform.common.job" />
To
<!-- Automatically scan components configured through annotations under the package com.common.aop and its subpackages -->
<context:component-scan base-package="com.platform.framework"/>
To
<!-- Activate automatic proxy function -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--
properties, settings, typeAliases, typeHandlers,
objectFactory, objectWrapperFactory, reflectorFactory,
plugins, environments, databaseIdProvider, mappers
-->
<configuration>

<!-- Setting management -->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- Print query statement -->
<setting name="logImpl" value="com.commonLogger" />
<setting name="callSettersOnNulls" value="true"/>
<setting name="jdbcTypeForNull" value="NULL"/>
</settings>

<!-- map hump handling -->
<objectWrapperFactory type="com.platform.framework.mybatis.map.MapWrapperFactory"/>

<!-- Plug-in management -->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
</configuration>

import org.apache.ibatis.logging.Log;

public class commonLogger implements Log {
public commonLogger(String clazz) {
}

public boolean isDebugEnabled() {
return true;
}

public boolean isTraceEnabled() {
return false;
}

public void error(String s, Throwable e) {
System.err.println(s);
e.printStackTrace(System.err);
}

public void error(String s) {
System.err.println(s);
}

public void debug(String s) {
System.out.println(s);
}

public void trace(String s) {
System.out.println(s);
}

public void warn(String s) {
System.out.println(s);
}
}

import java.util.Map;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.wrapper.ObjectWrapper;
import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;

public class MapWrapperFactory
implements ObjectWrapperFactory
{
public boolean hasWrapperFor(Object object)
{
return (object != null) && ((object instanceof Map));
}

public ObjectWrapper getWrapperFor(MetaObject metaObject, Object object)
{
return new commonLoggerMapWrapper(metaObject, (Map)object);
}
}

upload.properties

#================================================ ===========upload config properties=================================== ===========================
## Upload file path path (linux)
#uploadDir=/usr/local/tomcat/upload/
## Upload file path path (window)
uploadDir=D:\\dev_space\\workspaces\\newPlatform\\upload

CommonFreeMarkerView

package com.platform.framework.web.view;

import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.web.servlet.view.freemarker.FreeMarkerView;

import com.platform.consts.Constant;
import com.platform.consts.LoginConstant;

/**
* Override the freemark view parsing class
* @author pzh
*/
public class CommonFreeMarkerView extends FreeMarkerView {
To
@SuppressWarnings("unchecked")
@Override
protected void exposeHelpers(Map<String, Object> model,
HttpServletRequest request) throws Exception {
model.put("context_path", request.getContextPath()); //Context
String act = request.getParameter("act");
String menuCode = request.getParameter("menuCode");
model.put("pageAct", act);
if(Constant.READ.equals(act)) {
model.put("edited", "disabled"); //Operation is prohibited
}else{
model.put("edited", "");
}

//Handle the hiding of page buttons|display
List<Map<String, Object>> authActs = (List<Map<String, Object>>) request.getSession().getAttribute(LoginConstant.LOGIN_USER_AUTH_PERMISSION);
if(authActs !=null && authActs.size()>0) {
for (Map<String, Object> map: authActs) {
String actNo = map.get("actNo").toString();
if(menuCode != null && menuCode.equals(map.get("menuCode"))) {
if(Integer.valueOf(actNo) == 1) {
model.put(String.valueOf(map.get("actCode")), "");
}else{
model.put(String.valueOf(map.get("actCode")), map.get("actCode"));
}
}
}
}
super.exposeHelpers(model, request);
}
To
}

CommonAccessInterceptor

package com.platform.framework.web.interceptor.impl;

import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.platform.framework.context.ThreadContextHolder;
import com.platform.framework.web.interceptor.ILocalInterceptor;

public class CommonAccessInterceptor extends HandlerInterceptorAdapter{
To
@SuppressWarnings("unused")
private ILocalInterceptor localInterceptor; //Local custom interceptor, implemented by business code
To
/**
* Intercept all requests of spring mvc
* And set request and response to thread variables
* Realize request any where
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//Record the request object
ThreadContextHolder.setHttpRequest(request);
ThreadContextHolder.setHttpResponse(response);
To
//Illegal character filtering
Pattern pattern = Pattern.compile("'|<|>");
for(String[] paramValues: request.getParameterMap().values()){
for(String paramValue: paramValues){
if(pattern.matcher(paramValue).find()){
return false;
}
}
}
To
//The parent class only deals with the general part, and the localization business is realized by the specific business
// localInterceptor = SpringContextHolder.getBean("localInterceptor");
// if(null != localInterceptor)
// localInterceptor.preHandle(request, response, handler);
To
return super.preHandle(request, response, handler);
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
super.afterCompletion(request, response, handler, ex);
ThreadContextHolder.clearThreadValues();
}

}

CusViewsInterceptor

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

public class CusViewsInterceptor extends HandlerInterceptorAdapter{
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
super.postHandle(request, response, handler, modelAndView);
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return super.preHandle(request, response, handler);
}
}

log4j.properties

#Define LOG output level ERROR, WARN, INFO, DEBUG
#log4j.rootLogger=INFO,Console,File
log4j.rootLogger=INFO,Console
#Define the log output destination as the console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.Target=System.out
#Can flexibly specify the log output format, the following line is to specify the specific format
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%c]-%m%n
#Generate a new file when the file size reaches the specified size
log4j.appender.File=org.apache.log4j.RollingFileAppender
#Specify the output directory
log4j.appender.File.File=D:/logs/ssm.log
#Define the maximum file size
log4j.appender.File.MaxFileSize=10MB
#Output all logs, if you change to DEBUG, it means output logs of DEBUG or higher
log4j.appender.File.Threshold=ALL
log4j.appender.File.layout=org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern=[%p] [%d{yyyy-MM-dd HH\:mm\:ss}][%c]%m%n
#Control Framework Log
log4j.logger.org.springframework=ERROR
log4j.logger.org.mybatis=ERROR
log4j.logger.org.apache=ERROR

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final static Logger log = LoggerFactory.getLogger(AreaController.class);

import org.apache.log4j.Logger;
import java.text.MessageFormat;
private static Logger logger = Logger.getLogger(WorkManager.class);
logger.info(MessageFormat.format("====sys worker {0} syn date start time:{1}====", ruleCode,
DateUtil.formatTime(now)));

  • Taken
  • add comment
  • 0