Thinking: take the common add, delete, change and check as an example, we need to start the transaction when we implement the add, delete, change and check, and we need to submit the transaction after the execution is completed

If you have 100 methods for adding, deleting, or modifying a Service, each of those 100 methods needs to be concerned with the actions of starting a transaction or committing a transaction, in addition to the business logic you actually need to handle. Is there a slightly better way to do this? So the idea of a proxy pattern came into being. What is a proxy pattern?

1. What is the proxy mode

Simply put: a proxy is an enhancement to a target method.

What does that mean? Again, in the Service example, your business logic is called the target method that needs to be executed; Start a transaction, commit a transaction, these are what we call enhancements to the target method. So, can we write a separate class for “targets to be performed” (target class), a separate class for “actions to be enhanced” (enhancement class), and finally a class (proxy class), and combine the two together? In this case, the open transaction, commit transaction actions just need to be written in the enhancement class, and then we only care about our business actions in the business target class, and the rest of the mess such as open transaction, commit transaction (in addition to these can also be some other actions, Uniform logging operations, etc.) etc. I don’t care about these enhanced actions, just write business in the business class! Finally in the proxy class to enhance the action and target action combined with ok, and then use our proxy object. This enables the business class to focus on the business and nothing else, and achieves loose coupling (i.e., enhanced actions such as transactions, unified logging operations, etc., which are separate from my business).

Agents are classified into static agents and dynamic agents.

Let’s write it statically, just to realize the above content

2. Code implementation

package com.cj.study.proxy;
// Target interface
public interface PersonService {
	
	public void savePerson(a);
	
	public void updatePerson(a);
	
	public void deletePerson(a);
	
}
Copy the code
package com.cj.study.proxy;
/ / the target class
public class PersonServiceImpl implements PersonService{
 
	@Override
	public void savePerson(a) {
		System.out.println("Add");
	}
 
	@Override
	public void updatePerson(a) {
		System.out.println("Change");
	}
 
	@Override
	public void deletePerson(a) {
		System.out.println("Delete"); }}Copy the code

package com.cj.study.proxy;
/ / class
public class Transaction {
	public void beginTransaction(a){
		System.out.println("Open transaction");
	}
	public void commit(a){
		System.out.println("Commit transaction"); }}Copy the code
package com.cj.study.proxy;
/ / the proxy class
public class PersonServiceProxy implements PersonService{
	
	/ / the target class
	private PersonService personService;
	
	/ / class
	private Transaction transaction;
	
	// Use constructors to inject target and enhanced classes
	public PersonServiceProxy(PersonService personService,Transaction transaction){
		this.personService = personService;
		this.transaction = transaction;
	}
	
	@Override
	public void savePerson(a) {
		transaction.beginTransaction();
		personService.savePerson();
		transaction.commit();
	}
 
	@Override
	public void updatePerson(a) {
		transaction.beginTransaction();
		personService.updatePerson();
		transaction.commit();
	}
 
	@Override
	public void deletePerson(a) { transaction.beginTransaction(); personService.deletePerson(); transaction.commit(); }}Copy the code
package com.cj.study.proxy;
 
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
public class ProxyTest {
	@Test
	public void test(a){
		ApplicationContext context = new ClassPathXmlApplicationContext("com/cj/study/proxy/applicationContext-proxy.xml");
		PersonService personService = (PersonService)context.getBean("personServiceProxy"); personService.savePerson(); }}Copy the code

      
<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-2.5.xsd">
    
	<bean id="personServie" class="com.cj.study.proxy.PersonServiceImpl"></bean>
	
	<bean id="transaction" class="com.cj.study.proxy.Transaction"></bean>
	
	<bean id="personServiceProxy" class="com.cj.study.proxy.PersonServiceProxy">
		<constructor-arg index="0" ref="personServie"></constructor-arg>
		<constructor-arg index="1" ref="transaction"></constructor-arg>
	</bean>
	
</beans>
Copy the code

Final execution result:

3. Analyze the disadvantages of static proxies

Disadvantages of static proxy mode:

1. If a system has 100 Services, you need to create 100 proxy objects

2. If there are many methods in a Service that require transactions (enhanced actions), there is still a lot of duplicate code in the methods of the proxy object

3. It follows from the first and second points that static proxies are not very reusable

So what’s the solution?

Dynamic proxy can be used to solve the above problems

The next article will cover dynamic proxies: Java dynamic proxies and Cglib dynamic proxies and the differences

Tiezi, if you find the article helpful, you can click follow, click like

You can also pay attention to the public number, WX search: “chat 50 cents of Java”, welcome to learn to exchange, pay attention to the public number can receive the blogger’s Java learning video + information, ensure that are dry goods