A proxy is a common design pattern designed to provide a proxy for other objects to control access to an object. The proxy class is responsible for preprocessing messages for the delegate class, filtering messages and forwarding messages, and performing subsequent processing of the message after the class is executed. Before we talk about dynamic proxies, let's take a look at what a static proxy is, taking transaction control as an example.
1. Static proxy
1.1 Pom.xml File Configuration
<properties> <!--Spring--> <spring.version>4.1.3.RELEASE</spring.version> </propertie S> <dependencies> <!--Spring Begin--> <dependency> <groupid>org.springframewo Rk</groupid> <artifactId>spring-context</artifactId> <version>${spring.version}<
;/version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </ dependency> <dependency> <groupId>org.springframework</groupId> <artifactid> ;spring-webmvc</artifactid> <version>${spring.version}</version> </dependency> ;d ependency> <groupId>org.springframework</groupId> <artifactid>spring-jdbc</artif Actid> <version>${spring.version}</version> </dependency> <dependency> <groupid>org.sprin Gframework</groupid> <artifactId>spring-aspects</artifactId> <version>${spring.ver sion}</version> </dependency> <dependency> <groupid>org.springframework</groupi
D> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <!--Spring end--> </dependencies>
1.2 Business Interface Code
Public interface UserService {
/**
* *
feature Description: <br>
*〈 Save User
* *
@since [1.0.0] (optional)
Public
void Saveuser ();
/**
* *
feature Description: <br>
*〈 Update User
* *
@since [1.0.0] (optional)/public
void UpdateUser ( );
}
1.3 Business Implementation Class code
@Service ("UserService") Public
class Userserviceimpl implements UserService {
@Override public
Void Saveuser () {
System.out.println ("UserService saveuser () ...");
}
@Override public
void UpdateUser () {
System.out.println ("UserService updateuser () ...");
}
1.4 Transaction Management Class code
@Service ("TransactionManager") public
class TransactionManager {public
void BeginTransaction () {
SYSTEM.OUT.PRINTLN ("Open transaction ...");
}
public void Commint () {
System.out.println ("Commit transaction ...");
}
public void rollback () {
System.out.println ("ROLLBACK TRANSACTION ...");
}
1.5 proxy class Code
@Service ("Userserviceproxy") Public
class Userserviceproxy implements UserService {
@Resource (name = " UserService ")
private userservice userservice;
@Resource (name = "TransactionManager")
private TransactionManager TransactionManager;
@Override public
void Saveuser () {
try {
transactionmanager.begintransaction ();
Userservice.saveuser ();
Transactionmanager.commint ();
} catch (Exception e) {
transactionmanager.rollback ();
}
}
@Override public
void UpdateUser () {
try {
transactionmanager.begintransaction ();
Userservice.updateuser ();
Transactionmanager.commint ();
} catch (Exception e) {
transactionmanager.rollback ();}}}
1.6 Test Class Code
@RunWith (Springjunit4classrunner.class)
@ContextConfiguration (locations = {"Classpath:applicationContext.xml "}) public
class Proxytest {
@Resource (name =" Userserviceproxy ")
private userservice userservice;
@Test public
void Teststaticproxy () {
userservice.saveuser ();
}
}
1.7 Test Results
Open a transaction ....
UserService saveuser ()
... Commit TRANSACTION ....
From the above code, you can see the static agent to bring us a series of problems, such as in the proxy object contains a reference to the real object , if we need for different business agents, it is necessary for each business to create a proxy object, is very troublesome, so led to the dynamic agent.
2.JDK Dynamic Proxy
2.1 Business Class Interface
Public interface UserService {
/**
* *
feature Description: <br>
*〈 Save User
* *
@since [1.0.0] (optional) c19/>*/public
void Saveuser ();
/**
* *
feature Description: <br>
*〈 Update User
* *
@since [1.0.0] (optional)/public
void UpdateUser ();
}
2.2 Business Implementation Class
@Service ("UserService") Public
class Userserviceimpl implements UserService {
@Override public
Void Saveuser () {
System.out.println ("UserService saveuser () ...");
}
@Override public
void UpdateUser () {
System.out.println ("UserService updateuser () ...");
}
2.3 Transaction Management Class code
@Service ("TransactionManager") public
class TransactionManager {public
void BeginTransaction () {
SYSTEM.OUT.PRINTLN ("Open transaction ...");
}
public void Commint () {
System.out.println ("Commit transaction ...");
}
public void rollback () {
System.out.println ("ROLLBACK TRANSACTION ...");
}
2.4 Proxy class Code
@Service ("Transactionmanagerproxy") Public
class Transactionmanagerproxy implements Invocationhandler {
Private Object target;
@Resource (name = "TransactionManager")
private TransactionManager TransactionManager;
The public object Createproxyobject (object) {
This.target = object;
Return Proxy.newproxyinstance (This.getclass (). getClassLoader (), Target.getclass (). Getinterfaces (), this);
public object invoke (object proxy, Method method, object[] args) throws Throwable {
Transactionmanager.begintransaction ();
object = null;
try {
object = Method.invoke (target, args);
Transactionmanager.commint ();
} catch (Exception e) {
transactionmanager.rollback ();
}
return object;
}
2.5 Test Class Code
@RunWith (Springjunit4classrunner.class)
@ContextConfiguration (locations = {"Classpath:applicationContext.xml '} ' public
class Proxytest {
@Resource (name = "Transactionmanagerproxy")
private Transactionmanagerproxy Transactionmanagerproxy;
@Test public
void Teststaticproxy () {
UserService userservice = (userservice) Transactionmanagerproxy.createproxyobject (New Userserviceimpl ());
Userservice.saveuser ();
}
2.6 Test Results
Open a transaction ....
UserService saveuser ()
... Commit TRANSACTION ....
However, the dynamic proxy for JDK relies on the interface implementation, and if some classes do not implement the interface, the JDK proxy cannot be used, which requires the use of the Cglib dynamic proxy.
3.CGLIB Dynamic Proxy
3.1 Service Interface Class
Public interface UserService {
/**
* *
feature Description: <br>
*〈 Save User
* *
@since [1.0.0] (optional)
Public
void Saveuser ();
/**
* *
feature Description: <br>
*〈 Update User
* *
@since [1.0.0] (optional)/public
void UpdateUser ( );
}
3.2 Business Implementation Class
@Service ("UserService") Public
class Userserviceimpl implements UserService {
@Override public
Void Saveuser () {
System.out.println ("UserService saveuser () ...");
}
@Override public
void UpdateUser () {
System.out.println ("UserService updateuser () ...");
}
3.3 Transaction Management class
@Service ("TransactionManager") public
class TransactionManager {public
void BeginTransaction () {
SYSTEM.OUT.PRINTLN ("Open transaction ...");
}
public void Commint () {
System.out.println ("Commit transaction ...");
}
public void rollback () {
System.out.println ("ROLLBACK TRANSACTION ...");
}
3.4 Transaction proxy class
public class Transactionmanagerproxy implements Org.springframework.cglib.proxy.InvocationHandler {private Object tar
Get
Private TransactionManager TransactionManager;
Public Transactionmanagerproxy (Object target, TransactionManager transactionmanager) {this.target = target;
This.transactionmanager = TransactionManager;
//Create proxy Object public Object Getproxyinstance () {Enhancer enhancer = new enhancer ();
Enhancer.setclassloader (This.getclass (). getClassLoader ());
Enhancer.setsuperclass (Target.getclass ());
Enhancer.setcallback (this);
return Enhancer.create (); public object invoke (object proxy, Method method, object[] args) throws Throwable {Transactionmanager.begi
Ntransaction ();
object = null;
try {object = Method.invoke (target, args);
Transactionmanager.commint ();
catch (Exception e) {transactionmanager.rollback (); return object; }
}
3.5 Test class
@RunWith (Springjunit4classrunner.class)
@ContextConfiguration (locations = {"Classpath:applicationContext.xml '} ' public
class Proxytest {
@Resource (name = "TransactionManager")
private TransactionManager TransactionManager;
@Test public
void Teststaticproxy () {
Userserviceimpl Userserviceimpl = (userserviceimpl) New Transactionmanagerproxy (New Userserviceimpl (), TransactionManager). Getproxyinstance ();
Userserviceimpl.saveuser ();
}
3.6 Test Results
Open a transaction ....
UserService saveuser ()
... Commit TRANSACTION ....
The 1.CGLIB can generate subclasses of the target class and override methods of the parent class other than the final modifier.
2. The requirements of the class can not be final, to intercept the method to be final, not static, not private
3. The smallest unit of a dynamic proxy is a class (methods in all classes are processed)
Note: If the target object implements several interfaces, spring will use the JDK dynamic proxy, and if the target object does not implement any interfaces, spring uses the Cglib library to generate a subclass of the target object.