“This is the 13th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021”
The IOC and DI
IOC (Inversion of Control) is not a specific technology, but a design idea. In contrast to traditional control flow, IOC reverses control flow. In traditional programming, developers create and destroy objects themselves. In IOC, these operations are left to the framework so that developers don’t have to worry about implementation details and just use them.
The IOC is a good example of one of the principles of object-oriented design, the Hollywood law: ‘Don’t come to us, we’ll come to you.’ That is, the IOC container helps the object find the corresponding dependent object and inject it, rather than the object looking for it.
DI (Dependency Injection) means that the dependencies between components are automatically generated by the container at runtime. In other words, the container dynamically injects a Dependency into the component, thus increasing the reuse frequency of the component. Through the dependency injection mechanism, we can specify the resources needed by the target through simple configuration, and complete our business logic, regardless of where the resources come from, who implements them, etc.
In fact, IOC and DI are the same concept described from different angles. Because the concept of inversion of control is vague (it may only be understood as the level of container control objects, so it is difficult to think of who will maintain object relations), Martin Fowler, who was honored as “Godfather” by developers in 2004 (the world’s top expert, In contrast to IOC, dependency injection explicitly describes how “the injected object depends on the IOC container to configure the dependent object.”
extension
1. Advantages of Spring IOC
The advantages of IOC are as follows:
- Easier to use, ready to use, without explicit creation and destruction processes;
- It is easy to provide many services, such as transaction management, messaging services, etc.
- Support for singleton pattern is provided.
- It provides AOP abstraction, which makes it easy to implement permissions interception, runtime monitoring and other functions.
- More in line with object-oriented design laws;
- Low intrusive design with minimal code contamination reduces the complexity of business object replacement.
2.Spring IOC injection methods summary
There are three types of IOC injection: constructor injection, Setter injection, and interface injection.
Constructor injection
Constructor injection is implemented by relying on constructors. Constructors can take arguments or no arguments. We usually create class objects by using class constructors, each class object has a default constructor without arguments.
public class Person {
public Person(a) {}public Person(int id, String name) {
this.id = id;
this.name = name;
}
private int id;
private String name;
// Ignore Setter and Getter methods
}
Copy the code
Applicationcontext.xml is configured as follows:
<bean id="person" class="org.springframework.beans.Person">
<constructor-arg value="1" type="int"></constructor-arg>
<constructor-arg value="Java" type="java.lang.String"></constructor-arg>
</bean>
Copy the code
2. The Setter injection
Setter method injection is the current Spring mainstream injection method, it can use Setter/Getter methods defined by the Java Bean specification to complete injection, readability and flexibility are very high, it does not need to use declarative constructors, Instead, use Setter injection to set the related values directly, as shown in the following example:
<bean id="person" class="org.springframework.beans.Person">
<property name="id" value="1"/>
<property name="name" value="Java"/>
</bean>
Copy the code
3. Interface injection
Interface injection is a relatively old method of injection, because it requires the dependent object to implement unnecessary interface, invasive, so now has been completely abandoned, so this article is not going to do too much description, as long as you know there is such a thing on the line.
3.Spring AOP
AOP (aspect-oriented Programming) can be said to be the complement and perfection of OOP (Object-oriented Programing). OOP introduces concepts such as encapsulation, inheritance and polymorphism to establish a common object processing capability. OOP is powerless when we need to deal with common behavior, and THE emergence of AOP just solves this problem. For example, unified log processing modules, authorization validation modules, and so on can be easily handled using AOP.
Spring AOP currently offers three configurations:
- Java API-based approach;
- Based on @AspectJ (Java) annotations;
- Based on XML
<aop />
Label the way.
1. Java API-based approach
This configuration requires implementing relevant interfaces, such as MethodBeforeAdvice and AfterReturningAdvice, and defining the corresponding rules in the XML configuration.
Let’s start by defining an entity class as follows:
package org.springframework.beans;
public class Person {
public Person findPerson(a) {
Person person = new Person(1."JDK");
System.out.println("FindPerson executed");
return person;
}
public Person(a) {}public Person(Integer id, String name) {
this.id = id;
this.name = name;
}
private Integer id;
private String name;
// Ignore Getter and Setter methods
}
Copy the code
Advice class (); advice class (); advice class ();
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class MyAdvice implements MethodBeforeAdvice.AfterReturningAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("Ready to execute method:" + method.getName());
}
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println(method.getName() + "Method execution completed");
}
Copy the code
Then you need to configure the corresponding interception rule in the application. XML file as follows:
<! Define advisor -->
<bean id="myAdvice" class="org.springframework.advice.MyAdvice"></bean>
<! Find * --> find* -->
<bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="myAdvice"></property>
<property name="pattern" value="org.springframework.beans.*.find.*"></property>
</bean>
<! - define DefaultAdvisorAutoProxyCreator to make all the advisor configuration automatically - >
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
Copy the code
Can be seen from the above configuration, we need to configure a rules of the intercept method, and then define a DefaultAdvisorAutoProxyCreator to let all the advisor configuration automatically take effect.
Finally, we use the test code to make the call:
public class MyApplication {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("classpath*:application.xml");
Person person = context.getBean("person", Person.class); person.findPerson(); }}Copy the code
The execution results of the above programs are as follows:
Ready to execute method: findPerson findPerson is executed The findPerson method is finishedCopy the code
You can see that the AOP interception has been successful.
2. Based on @AspectJ annotations
Add the AspectJweaver JAR package to your project and configure it as follows:
<! -- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
Copy the code
This JAR package comes from AspectJ and is needed because Spring uses some of the annotations provided by AspectJ. After that, we need to turn on @AspectJ annotations in one of two ways.
You can turn on @Aspectj annotations in the application.xml configuration as follows:
<aop:aspectj-autoproxy/>
Copy the code
It can also be enabled using the @enableAspectJAutoProxy annotation as follows:
@Configuration
@EnableAspectJAutoProxy
public class AppConfig {}Copy the code
Then we need to declare the interceptor class and interception method, and configure the corresponding interception rules, the code is as follows:
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class MyAspectJ {
// Configure the interceptor class Person
@Pointcut("execution(* org.springframework.beans.Person.*(..) )"
public void pointCut(a) {}@Before("pointCut()")
public void doBefore(a) {
System.out.println("Execute the doBefore method");
}
@After("pointCut()")
public void doAfter(a) {
System.out.println("Execute doAfter method"); }}Copy the code
Then we just need to add the annotation class to the application.xml configuration as follows:
<bean class="org.springframework.advice.MyAspectJ"/>
Copy the code
Next, we add a method that needs to be intercepted:
package org.springframework.beans;
// The Bean to intercept
public class Person {
public Person findPerson(a) {
Person person = new Person(1."JDK");
System.out.println("Execute the findPerson method");
return person;
}
// Get other methods
}
Copy the code
Finally, we open the test code:
import org.springframework.beans.Person;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyApplication {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("classpath*:application.xml");
Person person = context.getBean("person", Person.class); person.findPerson(); }}Copy the code
The execution results of the above programs are as follows:
Execute the doBefore method execute the findPerson method execute the doAfter methodCopy the code
You can see that the AOP interception succeeded.
(3) based on XML<aop />
Way to label
The XML-based approach is similar to the annotation-based approach except that annotations are not required and relevant information is configured to application.xml as follows:
<! -- Interceptor handling class -->
<bean id="myPointcut" class="org.springframework.advice.MyPointcut"></bean>
<aop:config>
<! Interception rule configuration -->
<aop:pointcut id="pointcutConfig"
expression="execution(* org.springframework.beans.Person.*(..) )"/>
<! Interception method configuration -->
<aop:aspect ref="myPointcut">
<aop:before method="doBefore" pointcut-ref="pointcutConfig"/>
<aop:after method="doAfter" pointcut-ref="pointcutConfig"/>
</aop:aspect>
</aop:config>
Copy the code
After that, add a common class to intercept business processing, the implementation code is as follows:
public class MyPointcut {
public void doBefore(a) {
System.out.println("Execute the doBefore method");
}
public void doAfter(a) {
System.out.println("Execute doAfter method"); }}Copy the code
The method of interception and the test code are the same as the second annotation, which will not be described here.
Finally, the program is executed, and the execution result is:
Execute the doBefore method execute the findPerson method execute the doAfter methodCopy the code
You can see that the AOP interception succeeded.
The principle of Spring AOP is simple. It is a dynamic Proxy. When we call getBean(), we return an instance of the Proxy class, which is implemented in Spring using JDK Proxy or CgLib. Its core code is in DefaultAopProxyFactory#createAopProxy(…) , the source code is as follows:
public class DefaultAopProxyFactory implements AopProxyFactory.Serializable {
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<? > targetClass = config.getTargetClass();if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
// Determine whether the target class is an interface
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
// is a JDK proxy for the interface
return new JdkDynamicAopProxy(config);
}
// In other cases, use the CgLib proxy
return new ObjenesisCglibAopProxy(config);
}
else {
return newJdkDynamicAopProxy(config); }}// Ignore other code
}
Copy the code
summary
Spring AOP has been introduced to the concept of IOC and DI, as well as the advantages of IOC and the three ways of IOC injection: constructor injection, Setter injection, and interface injection. Java API-based approach, Java annotation-based approach, and XML tag-based approach.