Day 4 of Spring
@Resource
@Autowired
Difference:
1. @Autowired is Spring's own comment, the strongest
2. @Resource is J2EE. java standards
Because @Resource is standard, it is extensible. Even if your container is not using Spring. Switch to another framework and @Resource will work the same way.
@Autowired is Spring's own comment, so @Autowired can't be used without Spring.
Attention:
1. If you want to use @Autowired to auto-assemble, you need to bring some components with one of the four annotations. (Become a member first)
Note 2:
Reason: Because:
This type of TOTest does not have one of the four annotations added to it.
None of them are members of Spring.
We say that the framework automatically scans the classes labeled with four annotations under the base package.
There is also a dead-loop situation:
Why is there an endless loop?
Execution steps:
1. Your run test() method. Will go to a new IOTest object
2. As long as you go to new IOTest(), it will execute:
ApplicationContext ioc = new ClassPathXmlApplicationContext("ioc4.xml");
This sentence.
Once you execute this sentence. The IOTest class will be scanned. Because, above this class is @Component
3. After scanning, we will go to new IOTest().
At this point, it enters a cycle.
How do I use Spring's unit tests?
1. Guide:
spring-test-4.0.0.RELEASE
Why should we use Spring's unit tests? Is there a junit unit test?
Using Junit's unit test, we found that bookService cannot be assigned. Because the IOTest class does not have one of the four annotations added.
If you annotate the IOTest class, a dead-loop execution occurs again.
Therefore, in order to successfully assign a value to the bookService in this case, only Spring's unit test can be used, Junit's unit test is not possible.
Explanation: among@ContextConfiguration(locations = "classpath:ioc4.xml")Use this to specify Spring Location of the configuration file. @RunWith(SpringJUnit4ClassRunner.class)Specify which driver to use for unit testing, default is junit,Add this SpringJUnit4ClassRunner.class,Just put Junit Test changed to Spring Unit test. Previous@Test All by Junit Execute. @ContextConfiguration(locations = "classpath:ioc4.xml") @RunWith(SpringJUnit4ClassRunner.class) public class IOCTest { ApplicationContext ioc = null; @Autowired private BookService bookService; @Test public void test(){ System.out.println("bookService"+bookService); } }
The benefit of using Spring's unit tests is that we don't use ioc.getBean() to get components, we get them directly from Autowired, and Spring assembles them for us automatically.
Test dependency injection for generics. (Hard but important)
Why is generic dependency injection introduced?
First: Take a look at the original code architecture.
At the DAO level, there are three, BaseDao, BookDao,UserDao
BaseDao:
package com.rtl.dao; //This class defines some basic methods of addition, deletion, and alteration checking. public abstract class BaseDao<T> { public abstract void save(); }
2,BookDao:
package com.rtl.dao; import com.rtl.bean.Book; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Repository; @Repository public class BookDao extends BaseDao<Book> { @Override public void save() { System.out.println("BookDao Save Books ........."); } }
3,UserDao:
package com.rtl.dao; import com.rtl.bean.User; import org.springframework.stereotype.Repository; @Repository public class UserDao extends BaseDao<User>{ @Override public void save() { System.out.println("UserDao Save User....."); } }
There are two in the Service layer: BookService and UserService
BookService:
package com.rtl.service; import com.rtl.dao.BookDao; import com.rtl.servlet.BookServlet; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import javax.annotation.Resource; @Service public class BookService { @Resource private BookDao bookDao; public void save(){ bookDao.save(); } }
UserService:
package com.rtl.service; import com.rtl.dao.UserDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class UserService { @Autowired private UserDao userDao; public void save(){ userDao.save(); } }
Test class:
Test results:
Improved code:
Added a BaseService
UserService and BookService then inherit BaseService.
BaseService: This is a critical class.
Note: There are no four annotations on this class.
public class BaseService<T>{ @Autowired private BaseDao<T> baseDao; public void save(){ baseDao.save(); } }
Previous BaseDao was also uncommented.
UserService:
@Service public class UserService extends BaseService<User>{ }
BookService:
@Service public class BookService extends BaseService<Book>{ }
Test:
Question: In the BaseService class, there is no comment on its class. Why is the baseDaoa object not empty?
A:
Because this class inherits BaseService from BookService.
BookService adds the @Service comment.
Once inherited, the equivalent code is inside the BookService.
So baseDao is not null.
Strange things:
This baseDao is not null, but when you write code, idea says you are null. But you can run it again. Very strange!!!
Principle of generic dependency injection:
The conclusion is:
Previously, when we did injection matching:
1. Match by data type
2. The same is matched by the attribute name as the id.
Now there's one more thing: look at generics.
For example:
Match by data type BaseDao. So there are two:
One is BaseDao
Another is BaseDao
The reference at this point is to see what your generic type is.
IOC Summary:
IOC is a container that helps us manage components.
DI: Dependent on injection. Which components require other components require only a comment @Autowired for automatic assignment.
To use Spring, you first become a member of Spring. (That is, you have to add this component to the container first)
1. When the container starts, all single-instance objects are automatically created
2. When Autowired is assembled automatically, it looks for bean s that meet the requirements from inside the container
3. Use code:
ioc.getBean();
When a bean is retrieved in a form, it is actually found in a container
4. Container contains all bean s
Debug Spring's source code. See what a container really is?
Essentially Map.
This Map object saves all the bean s created and provides the outside world with the ability to get them.
Explore:
Which map is the single-instance bean saved in?
AOP:
Aspect Oriented Programming
AoP
OOP:
Object Oriented Programming
object-oriented programming
Face-oriented programming is a programming idea based on OOP.
Face-oriented programming means:
During program execution, dynamically break in a piece of code to a specified location for a specified method
Run
For example:
1. Build an interface with a method of adding, subtracting, multiplying and dividing.
public interface Calculator { int add(int i, int j); int sub(int i, int j); int mul(int i, int j); int div(int i, int j); }
2. Implementation Class:
package com.rtl.impl; import com.rtl.inter.Calculator; public class MyMathCalculator implements Calculator { @Override public int add(int i, int j) { int result = i + j ; return result; } @Override public int sub(int i, int j) { int result = i - j ; return result; } @Override public int mul(int i, int j) { int result = i * j ; return result; } @Override public int div(int i, int j) { int result = i / j ; return result; } }
3. Write test classes (not logged)
public class AOPTest { @Test public void test(){ Calculator calculator = new MyMathCalculator(); int result = calculator.add(1, 2); System.out.println(result); } }
Improvement:
Logging started:
First, add log printing inside each method.
Previous methods:
Now the method is:
Printing of this log is added to each method.
I found this way (add log printing inside each method.) It is not good to add a log, it is very difficult to maintain.
The second way is dynamic proxy.
Our core function is to add, subtract, multiply and divide.
Logging is only a secondary function of the system.
One way we do this is to couple core and ancillary functions.
We hope:
Core functionality remains unchanged, but ancillary functionality is added dynamically during the core functionality run.
Back here is an example:
Logging is added when adding, subtracting, multiplying and dividing are performed.
How?
Dynamic Proxy
Ideas:
Our method of adding, subtracting, multiplying and dividing is not to use our own new object (MyMathCalculator) and then call add() as an object.
Instead, find a way to use a proxy object to perform addition, subtraction, multiplication, and division.
At this point, the proxy object will help us call addition, subtraction, multiplication and division. And help us do something before and after the proxy object invokes addition, subtraction, multiplication and division.
For example:
Caculator proxy = CaculatorProxy.getProxy(Caculator);
proxy.add(1,2);
So here comes the question...:
How do I make a CaculatorProxy?
This CaculatorProxy is a class that helps Caculator generate proxy objects.
Dynamic proxy support in JDK
java.lang.reflect.Proxy
One of the methods in this class is:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)