当前位置:网站首页>@Do you know all these operations of Autowired?

@Do you know all these operations of Autowired?

2021-08-08 15:40:26 Su San said technology

hi, Hello everyone , I'm Susan , I'm meeting you again .

Preface

lately review When other people code , I saw some @Autowired Different usage , I think it's interesting , I spent some time studying , I got a lot of things , Now share with you .

Maybe @Autowired More powerful than you think .

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

1. @Autowired Default assembly for

We all know that spring in @Autowired annotation , It's used to assemble objects automatically . Usually , This is how we use it in projects :

package com.sue.cache.service;

import org.springframework.stereotype.Service;

@Service
public class TestService1 {
    public void test1() {
    }
}

    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
package com.sue.cache.service;

import org.springframework.stereotype.Service;

@Service
public class TestService2 {

    @Autowired
    private TestService1 testService1;

    public void test2() {
    }
}

    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

you 're right , It can be assembled successfully , Because by default spring It's assembled according to the type , That's what we're talking about byType The way .

Besides ,@Autowired Annotated required The default parameter is true, Means to turn on automatic assembly , Sometimes we don't want to use automatic assembly , You can set this parameter to false.

2. When there is more than one object of the same type

above byType This method is mainly used when there is only one object of the same type , At this point, the object type is unique , You can find the right object .

But if there is more than one object of the same type , What's going to happen ?

In the project test Under the table of contents , Build a class with the same name TestService1:

package com.sue.cache.service.test;

import org.springframework.stereotype.Service;

@Service
public class TestService1 {

    public void test1() {
    }
}

    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

When you restart the project :

Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'testService1' for bean class [com.sue.cache.service.test.TestService1] conflicts with existing, non-compatible bean definition of same name and class [com.sue.cache.service.TestService1]


    
  • 1.

It turned out to be wrong , There is a conflict in the name of newspaper , It directly leads to the failure to start the project .

Be careful , This is not the case when objects of the same type are Autowired There are two causes , It's very confusing . This is because spring Of @Service Method does not allow the same class name , because spring Will convert the first letter of the class name to lowercase , As bean The name of , such as :testService1, By default bean The name must be unique .

Let's see how to generate two identical types bean:

public class TestService1 {

    public void test1() {
    }
}

    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
@Service
public class TestService2 {

    @Autowired
    private TestService1 testService1;

    public void test2() {
    }
}

    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
@Configuration
public class TestConfig {

    @Bean("test1")
    public TestService1 test1() {
        return new TestService1();
    }

    @Bean("test2")
    public TestService1 test2() {
        return new TestService1();
    }
}

    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

stay TestConfig Class TestService1 example , And get rid of it TestService1 Class @Service annotation .

Restart project :watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk= Sure enough, the report was wrong , Tips testService1 Is a singleton , But found two objects .

In fact, there is another case where there are two identical types bean:

public interface IUser {
    void say();
}

    
  • 1.
  • 2.
  • 3.
@Service
public class User1 implements IUser{
    @Override
    public void say() {
    }
}

    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
@Service
public class User2 implements IUser{
    @Override
    public void say() {
    }
}

    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
@Service
public class UserService {

    @Autowired
    private IUser user;
}

    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

When the project restarts :

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk= Wrong report , The tip is the same as above ,testService1 Is a singleton , But found two objects .

The second situation is more common in actual projects , The following example , We focus on the second situation .

3. @Qualifier and @Primary

Clearly in spring in , according to Autowired The default assembly method :byType, There is no way to solve the above problems , Instead, assemble by name :byName.

Just add... To the code @Qualifier Annotations can be :

@Service
public class UserService {

    @Autowired
    @Qualifier("user1")
    private IUser user;
}

    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

Just adjust it like this , The project will start normally .

Qualifier It means qualified , General follow Autowired In combination with , One needs to be specified bean The name of , adopt bean Name to find what needs to be assembled bean.

Except for the top @Qualifier In addition to the notes , Can also be used @Primary Annotations solve the above problem . stay User1 Add... To it @Primary annotation :

@Primary
@Service
public class User1 implements IUser{
    @Override
    public void say() {
    }
}

    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

Get rid of UserService Upper @Qualifier annotation :

@Service
public class UserService {

    @Autowired
    private IUser user;
}

    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

Restart project , It works just as well .

When we use auto configuration to assemble Bean when , If this Bean There are multiple candidates , If one of the candidates has @Primary To modify , The candidate will be chosen , As auto configured values .

4. @Autowired Application scope of

In the above example @Autowired annotation , It's all used on member variables , but @Autowired The power of , Far from it .

Have a look first @Autowired Definition of annotations :watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

It can be seen from the figure that this annotation can be used in 5 On two target types , Let's summarize with a picture :

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk= The annotation we usually use most is probably on member variables .

Next , Let's focus on how to use it elsewhere ?

4.1 Member variables

Use... On member variables Autowired annotation :

@Service
public class UserService {

    @Autowired
    private IUser user;
}

    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

This is probably the most commonly used way .

4.2 Constructors

Use... On constructors Autowired annotation :

@Service
public class UserService {

    private IUser user;

    @Autowired
    public UserService(IUser user) {
        this.user = user;
        System.out.println("user:" + user);
    }
}

    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

Be careful , Add... To the constructor Autowired annotation , In fact, it still uses Autowired Assembly method , It's not a constructor assembly .

4.3 Method

Add... To the common method Autowired annotation :

@Service
public class UserService {

    @Autowired
    public void test(IUser user) {
       user.say();
    }
}

    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

spring During the start of the project , Automatic call once added @Autowired Method of annotation , We can do some initialization work in this method .

It can also be in setter On the way Autowired annotation :

@Service
public class UserService {

    private IUser user;

    @Autowired
    public void setUser(IUser user) {
        this.user = user;
    }
}

    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

4.4 Parameters

You can add to the input parameter of the constructor Autowired annotation :

@Service
public class UserService {

    private IUser user;

    public UserService(@Autowired IUser user) {
        this.user = user;
        System.out.println("user:" + user);
    }
}

    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

You can also add... To the input parameter of a non static method Autowired annotation :

@Service
public class UserService {

    public void test(@Autowired IUser user) {
       user.say();
    }
}

    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

4.5 annotation

It doesn't work much , I just want to introduce more .

5. @Autowired High end play

In fact, the above examples are all through @Autowired Automatically assemble a single instance , But here I'll tell you , It can also automatically assemble multiple instances , What's going on ?

take UserService Adjust the method , Use one List Gather to receive IUser Parameters of type :

@Service
public class UserService {

    @Autowired
    private List<IUser> userList;

    @Autowired
    private Set<IUser> userSet;

    @Autowired
    private Map<String, IUser> userMap;

    public void test() {
        System.out.println("userList:" + userList);
        System.out.println("userSet:" + userSet);
        System.out.println("userMap:" + userMap);
    }
}

    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

Add one more controller:

@RequestMapping("/u")
@RestController
public class UController {

    @Autowired
    private UserService userService;

    @RequestMapping("/test")
    public String test() {
        userService.test();
        return "success";
    }
}

    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

After calling the interface :

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk= As you can see from the picture above :userList、userSet and userMap Both print out two elements , explain @Autowired Will automatically put the same type of IUser Objects are collected into the collection .

No surprise , Isn't surprise ?

6. @Autowired I'm sure it will be assembled ?

Previously, I introduced @Autowired There's so much bullshit about it , In fact, in some cases , Even if @Autowired The object of assembly is still null, What is the reason ?

6.1 No addition @Service annotation

I forgot to add @Controller、@Service、@Component、@Repository Etc ,spring Can't complete the function of automatic assembly , for example :

public class UserService {

    @Autowired
    private IUser user;

    public void test() {
        user.say();
    }
}

    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

This should be the most common mistake , Not because you're handsome , Would not have made such a low-level mistake .

6.2 Inject Filter or Listener

web The order in which the application starts is :listener->filter->servlet.

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

Let's take a look at this case :

public class UserFilter implements Filter {

    @Autowired
    private IUser user;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        user.say();
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

    }

    @Override
    public void destroy() {
    }
}

    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.setFilter(new UserFilter());
        bean.addUrlPatterns("/*");
        return bean;
    }
}

    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

An error will be reported when the program is started :

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=tomcat Unable to start properly .

What's the reason ?

as everyone knows ,springmvc The start of is in DisptachServlet It's made in it , And it's in listener and filter After performing . If we want to listener and filter Inside @Autowired Some bean, Surely not , because filter When initializing , here bean It's not initialized yet , Can't auto assemble .

If it really needs to be done at work , How can we solve this problem ?

public class UserFilter  implements Filter {

    private IUser user;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(filterConfig.getServletContext());
        this.user = ((IUser)(applicationContext.getBean("user1")));
        user.say();
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

    }

    @Override
    public void destroy() {

    }
}

    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.

The answer is to use WebApplicationContextUtils.getWebApplicationContext Get current ApplicationContext, And through it we get bean example .

6.3 The annotation was not modified @ComponentScan scanning

Usually ,@Controller、@Service、@Component、@Repository、@Configuration Etc , It needs to pass @ComponentScan Annotation scan , Collecting metadata .

however , If you don't add @ComponentScan annotation , perhaps @ComponentScan The path of the annotation scan is wrong , Or the path range is too small , Some annotations cannot be collected , It can't be used in the back @Autowired Complete the function of automatic assembly .

The good news is , stay springboot In the project , If used @SpringBootApplication annotation , It's built in with @ComponentScan The function of annotation .

6.4 The problem of circular dependence

If A Depend on B,B Depend on C,C And depend on A, This creates a dead cycle .

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=spring Of bean The default is singleton , If a single example bean Use @Autowired Automatic assembly , In most cases , It can solve the problem of circular dependence .

But if bean Is more cases , There will be circular dependency problems , Lead to bean Automatic assembly doesn't work .

And in some cases , If you create a proxy object , Even if bean Is a singleton , There will still be circular dependency problems .

If you're interested in circular dependency , You can also take a look at my other topic 《》, It's very detailed .

7. @Autowired and @Resouce The difference between

@Autowired Powerful as it is , But there are also some shortcomings . such as : For example, it's related to spring Strong coupling , If you change it to JFinal Etc , The function will fail . and @Resource yes JSR-250 Provided , It is Java standard , Most frameworks support .

besides , Some scenes use @Autowired Demands that cannot be met , Change to @Resource But it can solve the problem . Next , Let's focus on @Autowired and @Resource The difference between .

  • @Autowired Press default byType Automatic assembly , and @Resource Default byName Automatic assembly .

  • @Autowired Contains only one parameter :required, Indicates whether automatic admission is enabled , The default is true. and @Resource It contains seven parameters , The two most important parameters are :name and type.

  • @Autowired If you want to use byName, Need to use @Qualifier Work together . and @Resource If you specify name, Then use byName Automatic assembly , If you specify type, Then use byType Automatic assembly .

  • @Autowired Can be used in : Constructors 、 Method 、 Parameters 、 Member variables and annotations , and @Resource It can be used in : class 、 Member variables and methods .

  • @Autowired yes spring Defined comments , and @Resource yes JSR-250 Defined comments .

Besides , They are assembled in different order .

@Autowired The assembly sequence is as follows :

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

@Resource The assembly sequence is as follows :

  1. If you also specify name and type:watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

  2. If you specify name:watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

  3. If you specify type:watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

  4. If neither name, There is no designation type:

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

Postscript

I was going to write next @Autowired Principle analysis and source code interpretation , But because it's too long , It doesn't fit together , I'm going to have a special topic later . If interested friends , Can continue to follow my follow-up articles , I believe you will get something after reading it .

 

版权声明
本文为[Su San said technology]所创,转载请带上原文链接,感谢
https://chowdera.com/2021/08/20210808152534675A.html

随机推荐