1 simple factory mode
When object a needs to call the method of object B, we need to create a new instance of B in A. we call this method hard coding coupling. The disadvantage is that once the requirements change, such as using class C to replace B, we have to rewrite the method of class A.
If thousands of classes in the application are hard coded to couple B, it will be a headache.
Therefore, there is a simple factory mode, also known as static factory method. A factory class dynamically determines which product class should be created according to the incoming parameters.
BeanFactory in Spring is the embodiment of the simple factory pattern. BeanFactory is a core interface in the Spring IOC container. Its definition is as follows:
Bean can be obtained through its specific implementation class (such as ClassPathXmlApplicationContext):
BeanFactory bf = new ClassPathXmlApplicationContext("spring.xml"); User userBean = (User) bf.getBean("userBean");
Users do not need to create new by themselves, but get object instances through the method get Bean of the factory class. This is the simple factory pattern, but Spring creates beans with reflection.
2 factory method mode
In a simple factory, the factory class performs all logical judgment and instance creation.
If you don't want to judge in the factory class, you can provide different factories for different products. Different factories produce different products. Each factory corresponds to only one corresponding object. This is the factory method mode.
Spring FactoryBean
Define a class UserFactoryBean to implement the FactoryBean interface, mainly to create a new User object in the getObject method.
In this way, the User instance generated by the factory is obtained through getBean(id), not the UserFactoryBean itself:
BeanFactory bf = new ClassPathXmlApplicationContext("user.xml"); User userBean = (User) bf.getBean("userFactoryBean");
3. Singleton mode
Only one instance of a class is allowed during the operation of the whole system.
Spring beans are singleton mode by default. Spring uses the singleton Registry (HashMap) method:
public class DefaultSingletonBeanRegistry { // Use ConcurrentHashMap to save various single instance objects private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>; protected Object getSingleton(String beanName) { // Get the Object in the Map first Object singletonObject = singletonObjects.get(beanName); // If not, create an object instance through reflection and add it to HashMap if (singletonObject == null) { singletonObjects.put(beanName, Class.forName(beanName).newInstance()); } // Return object instance return singletonObjects.get(beanName); } }
4 agent mode
It implements the same interface as the proxy object. The client must interact with the proxy target class through the proxy. The proxy generally performs some specific processing in the process of interaction (before and after interaction), such as pre-processing before calling this method and post-processing after calling this method.
benefit
Some common logic can be added based on the business functions of the target object. For example, if we want to add logging, permission management and transaction control functions to the target object, we can use the proxy class to complete it without modifying the target class, so as to maintain the stability of the target class.
Comply with the opening and closing principle, and do not modify the code or method written by others at will.
Agents are divided into
Static proxy
An interface needs to be defined. The proxy object (target object) and proxy object (Proxy) implement the same interface together:
// Abstract interface public interface IStudentDao { void save(); } // Target object public class StudentDao implements IStudentDao { public void save() { System.out.println("Saved successfully"); } } // Proxy object public class StudentDaoProxy implements IStudentDao{ //Holds a reference to the target object private IStudentDao target; public StudentDaoProxy(IStudentDao target){ this.target = target; } //Add transaction control before and after the target function object method public void save() { System.out.println("Start transaction"); target.save();//Method of executing target object System.out.println("Commit transaction"); } } public static void main(String[] args) { //Create target object StudentDao target = new StudentDao(); //Create a proxy object, transfer the target object to the proxy object, and establish a proxy relationship StudentDaoProxy proxy = new StudentDaoProxy(target); //The method of the agent is executed proxy.save(); }
Dynamic agent
Spring AOP adopts dynamic proxy, that is, the proxy class is dynamically created by the JVM when the program runs.
In the example of static proxy, the proxy class (StudentDaoProxy) is customized and has been compiled before the program runs.
The dynamic proxy class is not defined in Java code, but dynamically generated at runtime according to our "instructions" in Java code.
How to "instruct" JDK to dynamically generate proxy classes?
In Java Lang.reflect package provides a Proxy class and an InvocationHandler interface, through which dynamic Proxy objects can be generated:
1. Define an InvocationHandler class and put the logic to be extended into this class.
For example, the following example simulates adding transaction control:
public class MyInvocationHandler implements InvocationHandler { private Object obj; public MyInvocationHandler(Object obj){ this.obj=obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Start transaction"); Object result = method.invoke(obj, args); System.out.println("Start transaction"); return result; } }
- Create proxy objects dynamically using Proxy#newProxyInstance
public static void main(String[] args) { //Create target object StudentDao IStudentDao stuDAO = new StudentDao(); //Create MyInvocationHandler object InvocationHandler handler = new MyInvocationHandler(stuDAO); //Use proxy Newproxyinstance dynamically creates a proxy object stuProxy IStudentDao stuProxy = (IStudentDao) Proxy.newProxyInstance(stuDAO.getClass().getClassLoader(), stuDAO.getClass().getInterfaces(), handler); //Method of using proxy object stuProxy.save(); }
The advantage of dynamic proxy is that it can easily handle the functions of proxy classes uniformly without modifying the methods in each proxy class.
Spring implements the method level aspect enhancement of the class through the dynamic proxy, that is, dynamically generate the proxy class of the target object, set the interceptor in the method of the proxy class, and enhance the function of the proxy method by executing the logic in the interceptor, so as to realize AOP.