Spring基础篇:注解编程

简介: Spring基础篇:注解编程

第一章:注解基础概念

一:什么是注解编程

在类或者方法上添加特定的注解,进而完成特定的功能的开发

二: 为什么要注解编程

1:注解开发方便,代码简洁,开发速度大大提高。

2:Spring开发的潮流,Spring2.X引入注解,目的就是为了某些情况下可以简化我们的XML配置,作为XML配置开发的有益补充

3:Spring3.x完善注解:目的就是为了替换XML基于纯注解进行注解编程

4:Spring4之后就提倡使用注解进行常见的开发。

这么好的东西为什么现在才将,XML现在都没人用了,为什么不直接上注解?

1:两个一块讲的话,一个不懂,全都完蛋

2:Spring的注解设计的有点混乱,基础不扎实,思考不全面,直接懵逼了。

在Spring框架应用注解时,如果对注解配置的内容不满意,可以通过Spring配置文件进行覆盖。

三:注解的作用

1:替换Xml这种配置形式来简化配置

1、曾经在Spring当中我们配置Service层的某对象的时候,需要在Spring的核心配置文件里边对这些Service层的Bean进行注册,配置Bean标签,通过Bean标签的话,创建他的对象交由Spring容器进行管理。

2、引入注解之后,在开发完这个类之后,我们只需要在这类上边加一个注解就可以了,@Component就可以了,通过这个注解,就相当于加了这个Bean标签了,简化了开发,通过这种注解的方式进行配置,比使用标签的形式进行配置,简化了很多。

2:替换接口、实现调用双方的契约性

执行一个功能的时候,会涉及到两个角色,就是功能的调用者和功能的提供者,比如说功能的调用者叫做,Consumer功能的提供者叫做Provider,功能的提供者提供了一个M1方法,功能写到了这个方法当中,在Comsumer中的invoke方法中调用这个方法进行调用的时候,如何保证一定可以调用的到这个方法呢?(这种情景就好比是JDBC调用数据库jar包获取链接的时候,也好比是Spring创建额外功能需要实现MethodInterCeptor接口一样)怎么解决这个问题呢?就是在调用者和提供者之间提供一个契约性,这个契约性可以由接口进行保证,提供者需要实现这个接口,实现接口中提供的抽象方法,就保证了调用的规范性和契约性,就可以了。

虽然我们可以通过接口实现这样的功能,保证调用和被调用双方的一个规范性,但是这样也存在着问题,比如说:在web开发过程中,我们需要写Servlet,Servlet就是一个接口,在Servlet当中我们规定了几个方法,init,service,destroy,getServletConfig,getServletInfo这几个方法,作为这个接口来讲,已经达成了Tomcat与我们程序员直接的约定,程序员写的代码最终需要由Tomat来调用,程序员我们把我们的代码写在哪,Tomcat就能认识呢?我们程序员写Servlet,Tomcat调用Servlet,就达成了这样的契约关系。但是作为程序员来讲我们只需要实现这个Service这个方法就好了,但是还有一堆其他的方法需要来实现, 这样的话就很烦,我们最终是如何解决这个问题的呢?是通过一种适配器的方式,适配器HttpServelet就被解决了,在注解诞生之后,我们也可以产生一种锲约关系,这样就解决了实现接口需要实现所有的抽象方法的情况

注解是如何来解决这个事的呢?

如果我将来想要调用者能够调用我们的方法,我们就需要在提供者某个方法上添加一个注解,调用者需要调用的这些方法,这样的话,调用者就可以通过反射的方式扫描这些信息,哪些方法有注解,就可以识别出来来进行调用。作为注解的作用,完全可以作为调用的方式。这样将来我们研究全注解Aop开发的时候,就可以通过这样的形式完成Aop的开发,不用实现任何的接口。不同形式的Aop开发表象是不一样的,但是呈现出来的结果是完全一致的。但是呢,注解更加灵活,成为了当前主流的配置形式。

四:Spring注解发展历程

Spring经过若干版本的更迭之后,才给我们展示出来了当前的注解的内容,他的发展历程是这样的:

1、Spring2.x之后开始支持注解编程 @Componet @Service @Scope Spring提供这样的注解是为了简化Xml开发的配置,作为Xml开发的有益补充。

2、Spring3.x之后提供了 @Configureation @Bean这样的注解,希望能够彻底XML实现纯注解编程

3、Spring4.x之后,引申出来了一个跨时代的框架SpringBoot之后,Spring提倡使用注解进行常见的开发

4、Spring5.x之后,变化不大。

五:Spring注解开发的一个问题

Spring基于注解进行配置之后,还能够解耦合吗?

Spring提供配置文件的目的呢,就是为了把代码中的一些内容书写到配置文件当中,这样呢日后在改的过程中,不需要进行重新编译,重新部署,但是呢,基于注解进行配置之后,我们的配置内容会写代码里边,这样的话在修改配置后,在代码中进行修改,作为Spring框架来讲他们也已经帮我们考虑到了,在Spring框架应用注解时如果对注解配置的内容不满意,我们是可以通过Spring配置文件进行覆盖的,如果我们对注解不满意,不需要该注解,只需要在配置文件中进行配置覆盖即可,这样也进行了解耦合的作用

第二章:Spring基础注解

这个阶段的注解是Spring2.x版本提供的。这个阶段的注解仅仅是简化了XML的配置,并不能完全代替XML

一:对象创建相关注解

搭建开发环境的时候需要在核心配置文件当中添加这样的一个标签,这个标签配置一个对应的属性base-package,我们日后需要根据需要在类上添加注解,通过这个标签的使用,目的是为了让Spring去扫描注解,进而扫描到注解之后就可以对这些对象进行创建和配置。配置base-package = "com.dashu"属性之后,Spring就会在这个包及其子包当中扫描来让注解生效。

<context:component-scan base-package = "com.dashu"/>

1:@Component

这个注解用于替换Bean标签

在原来的开发过程中,写了一个类之后,需要对应的写一个Bean标签,但是在这有两个细节需要关注,作为Bean标签可以通过这个属性可以代替,但是这里边的id属性和class属性如何被代替呢?class属性对应的是类的全限定类名,这样的话,我们完全可以通过反射的形式来获取,但是这个id属性,实际上对于我们更为重要,标签当中id属性是由我们来设置的。

Componet注解开发方式有一个默认的id配置形式,就是这个类名<首单词首字符小写>,应用了这个注解之后默认的id值就是这个类的类名首单词首字母小写。

将来我们的UserDao的话,我们指定的id值是userDao这就是Componet对于id的支持,提供了一种默认的id值

1):开发过程

<beans xmlns="http://www.springframework.org/schema/beans">
    <context:component-scan base-package = "com.dashu"/>
</beans>
package com.dashu.test;
public class TestClass {
    @Test
    public void testOne(){
        ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
        User user = (User) ctx.getBean("user");
        System.out.println("user="+user.getClass());
    }
}
#resources?件夹根?录下
log4j.rootLogger=debug,console
#日志输出到控制台
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target=System.Out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
#log4j.appender.console.layout.ConversionPattern=[caoshanshan] %d{yyyy-MM-dd HH:mm:ss,SSS} - %-4r %-5p [%t] %C:%L %x - %m%n
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
2021-07-31 17:49:05 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'user'
user=class com.dashu.bean.User
package com.dashu.bean;
@Component
public class User implements Serializable {
    private Integer id;
    private String name;
    private String password;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}

2):如何显示指定工厂创建对象的id值

@Component(“u”)

package com.dashu.bean;
@Component("u")
public class User implements Serializable {
    private Integer id;
    private String name;
    private String password;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}

3):配置文件可以覆盖注解中配置的内容

需要在ApplicaitonContext.xml中需要进行对应的配置。Xml覆盖注解需要保证id值完全一致才能进行覆盖这个是核心的要点。

如果要是覆盖就需要保证id值一致,如果不一致实际上Spring就会把他当做一个新的对象,不进行覆盖,先创建注解,在创建Xml

2021-07-31 18:03:52 DEBUG ClassPathXmlApplicationContext:590 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@79ad8b2f
2021-07-31 18:03:52 INFO  KotlinDetector:57 - Kotlin reflection implementation not found at runtime, related features won't be available.
2021-07-31 18:03:52 DEBUG ClassPathBeanDefinitionScanner:437 - Identified candidate component class: file [D:\giteesource\spring\spring-annotation\target\classes\com\dashu\bean\User.class]
2021-07-31 18:03:53 DEBUG XmlBeanDefinitionReader:396 - Loaded 7 bean definitions from class path resource [applicationContext.xml]
2021-07-31 18:03:53 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
2021-07-31 18:03:53 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
2021-07-31 18:03:53 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
2021-07-31 18:03:53 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
2021-07-31 18:03:53 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
2021-07-31 18:03:53 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean **'u'**
2021-07-31 18:03:53 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean **'user'**

1:@Component衍生注解

@Repository && @Service && @Controller 我们称这三个注解是@Component的衍生注解

注意:本质上这三个衍生注解就是@Component。他们的作用 细节 用法都是完全一致,这些注解上边有@Component修饰

作为衍生注解来讲作用和这些注解完全一致相当于Bean标签。使用和@Component完全一致

提供衍生注解的核心目的是为了准确表达一个类的核心作用,比如我们@Repository建议应用在Dao层的上边,他是专门应用在Dao层上的,@Service是应用在Service层上的,@Controller也应用在Controller层上的,在我们Spring整合Mybatis开发过程中不适用@Repository当中,因为我们不写Dao层的实现类,我们没有机会写,所以我们使用Mybatis独有的方式创建对象

2:@Scope

作用:控制(简单对象)的创建次数

这个是对应Bean标签当中的Scope属性,单例设计模式,多例设计模式,如果不添加这个注解,默认不写是Singleton

3:@Lazy

作用:用于延时创建单实例对象,对于单实例对象,Spring工厂默认会在Spring工厂创建的时候创建的时候创建这个对象,但是如果在这个类对应的Bean标签当中指定了lazy属性为true,就延时创建Bean,现在我们使用注解是相同的作用,加上这个@Lazy之后,我们就可以延时创建对象。也就是什么时候getBean,什么时候在创建对象

二:生命周期相关注解

1:生命周期注解概述

1:初始化相关方法
InitializingBean<bean init-method="myInit"/>
2:销毁方法
DisposableBean
<bean destory-method="myDestroy"/>

现在我们应用注解之后,我们的使用注解的方式也可以达到这样的需求,@PostConstruct,@PreDestroy这两个注解并不是Spring提供的,是JSR520提供的,JSR是JavaEE规范,Spring兼容了这个规范。这两个注解并不是Spring原生提供的,我们再次通过注解实现了接口的契约性,之前我们通过接口达到了契约性,现在是通过注解达到了契约性。

2:生命周期注解使用示例

@Component
public class Product {
    @PostConstruct
    public void myInit(){
        System.out.println("Product.myInit");
    }
    @PreDestroy
    public void myDestroy(){
        System.out.println("Product.myDestroy");
    }
}
@Test
    public void testFour(){
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
        System.out.println("------------");
        ctx.close();
    }
2021-07-31 18:40:36 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'u'
2021-07-31 18:40:36 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'product'
Product.myInit
2021-07-31 18:40:36 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'user'
------------
2021-07-31 18:40:36 DEBUG ClassPathXmlApplicationContext:987 - Closing org.springframework.context.support.ClassPathXmlApplicationContext@79ad8b2f, started on Sat Jul 31 18:40:35 CST 2021
Product.myDestroy

三:注入相关注解

1:用户自定义类型注入

1):@AutoWired

应用注解,我们还是需要使用Set注入

@Test
    public void testFive(){
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
        UserService userService = (UserService) ctx.getBean("userServiceImpl");
        userService.register();
    }
@Service
public class UserServiceImpl implements UserService {
    private UserDao userDao;
    public UserDao getUserDao() {
        return userDao;
    }
    @Autowired
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    @Override
    public void register() {
        System.out.println("UserServiceImpl.register");
        userDao.save();
    }
}
@Repository
public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("UserDaoImpl.save");
    }
}
2021-07-31 18:59:40 DEBUG ClassPathXmlApplicationContext:590 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@79ad8b2f
2021-07-31 18:59:40 INFO  KotlinDetector:57 - Kotlin reflection implementation not found at runtime, related features won't be available.
2021-07-31 18:59:41 DEBUG ClassPathBeanDefinitionScanner:437 - Identified candidate component class: file [D:\giteesource\spring\spring-annotation\target\classes\com\dashu\bean\User.class]
2021-07-31 18:59:41 DEBUG ClassPathBeanDefinitionScanner:437 - Identified candidate component class: file [D:\giteesource\spring\spring-annotation\target\classes\com\dashu\injection\UserDaoImpl.class]
2021-07-31 18:59:41 DEBUG ClassPathBeanDefinitionScanner:437 - Identified candidate component class: file [D:\giteesource\spring\spring-annotation\target\classes\com\dashu\injection\UserServiceImpl.class]
2021-07-31 18:59:41 DEBUG ClassPathBeanDefinitionScanner:437 - Identified candidate component class: file [D:\giteesource\spring\spring-annotation\target\classes\com\dashu\life\Product.class]
2021-07-31 18:59:41 DEBUG ClassPathBeanDefinitionScanner:437 - Identified candidate component class: file [D:\giteesource\spring\spring-annotation\target\classes\com\dashu\test\Customer.class]
2021-07-31 18:59:41 DEBUG XmlBeanDefinitionReader:396 - Loaded 11 bean definitions from class path resource [applicationContext.xml]
2021-07-31 18:59:41 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
2021-07-31 18:59:41 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
2021-07-31 18:59:41 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
2021-07-31 18:59:41 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
2021-07-31 18:59:41 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
2021-07-31 18:59:41 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'u'
2021-07-31 18:59:41 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'userDaoImpl'
2021-07-31 18:59:41 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'userServiceImpl'
2021-07-31 18:59:41 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'product'
Product.myInit
2021-07-31 18:59:41 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'user'
UserServiceImpl.register
UserDaoImpl.save
@Service
public class UserServiceImpl implements UserService {
    private UserDao userDao;
    public UserDao getUserDao() {
        return userDao;
    }
    @Autowired
    @Qualifier("userDaoImpl")
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    @Override
    public void register() {
        System.out.println("UserServiceImpl.register");
        userDao.save();
    }
}

A:@Autowired注解基于类型进行注入

我们需要把对应的@Autowired注解放到set方法上,他是基于类型进行注入的。他必须是成员变量相同的类型,或者是我的子类,乃至我接口的实现类。这就是我们基于类型完成注入的原理,在注入对象的类型必须得是目标成员边量相同的类型,实现类,或者子类。

B:@Autowired+@Qualifier基于名字进行注入

想要基于名字进行注入仅仅有一个AutoWired是不够的,我们需要有一个另一个注解,他俩组合才能够基于名字(id值)进行注入

C:@Autowired注解的放置位置

对应成员变量的上边,成员变量对应set方法上,我们将注解放置在set方法上的时候Spring就会调用Set方法来进行赋值,这个可以自己测试一下,确实如此,但是我们也可以直接把他放在成员边量的上边,此时依然是可以注入成功的,但是这样的话Set方法就没被Spring调用,他是通过暴力反射的方式进行赋值的。对应的Qualifier也是可以随着Autowired注解的位置改变而改变。

2):@Resource

作为JavaEE当中提供了@Resource这个注解来进行注入,这个注解本身就是基于名字进行注入的,他自己就等于A+Q进行组合@Resource(“userDaoImpl”)

这个@Resource注解当我们不指定名字时,直接应用这个注解,不写名字时,他就会基于类型来进行注入,这就是我们的这个Resource注解强大的地方。

JSR330规范中也提供了一个注解@Inject这个注解的作用和我们的Autowired是完全一致的,这个也就是基于类型进行注入的。如果想使用他的话我们需要引入他的JAR包。这个注解实际上在EJB3.0当中引用的比较多,但是实际上EJB3.0已经黄了,所以知道这个注解和使用方式的很少。

2:JDK类型注入

1):@Value注入说明

针对于JDK类型的数据在XML当中我们是通过Property标签对这些类型进行注入,通过value属性或者标签进行注入,然而,我们现在想要通过注解,里边的Property标签已经没有地方写了,这个问题怎么解决呢?这个东西是不可能写在代码里边的,这样的话就出现了耦合。我们把这些注入作为数据写在properties标签当中来进行注入。这个properties文件的名字随便起,保证key-value形式就好,中间用 = 间隔,这些Property文件将来Spring会进行使用。

那么我们应该怎么进行配置呢?我们完全可以通过Spring为我们提供的一个标签来进行读取和整合,这个标签写在Spring核心配置文件当中,这个标签叫做,<context:property-placeholder location = “classpath:/xxx.properties”/>通过这个标签的配置Spring就可以获取到响应的配置文件的配置信息,那么Spring获取到之后如何将这些配置信息如何进行注入呢?比如说:如何为User当中的id和属性进行赋值呢?只需要在User这个类当中通过@Value这个注解进行赋值,在注解当中通过${key}来获取相应的值,就可以完成注入操作。

总结:

1、注入的值写在Properties当中

2、整合Spring核心配置文件和Properties文件

3、通过@Value注解进行值的获取

注解写在属性上是使用的是反射进行赋值,注解写在set方法上使用的set方法进行赋值。

2):@Value注入使用

![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/2a4c1502837148efa2b0f97d80e617f6.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0ZhY2lhbF9NYXNr,size_16,color_FFFFFF,t_70)

id = 10
name = shit
<bean id="user" class = "com.dashu.bean.User"/>
    <context:property-placeholder location="classpath:init.properties"/>
/**
 * @Auther: DaShu
 * @Date: 2021/7/31 21:13
 * @Description:
 */
@Component
public class Catagory {
    @Value("${id}")
    private Integer id;
    @Value("${name}")
    private String name;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
@Test
    public void testSix(){
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
        Catagory catagory = (Catagory) ctx.getBean("catagory");
        System.out.println(catagory.getId());
        System.out.println(catagory.getName());
        //10
        //shit
    }
/**
 * @Auther: DaShu
 * @Date: 2021/7/31 21:13
 * @Description:
 */
@Component
public class Catagory {
    private Integer id;
    private String name;
    public Integer getId() {
        return id;
    }
    @Value("${id}")
    public void setId(Integer id) {
        System.out.println("Catagory.setId");
        this.id = id;
    }
    public String getName() {
        return name;
    }
    @Value("${name}")
    public void setName(String name) {
        System.out.println("Catagory.setName");
        this.name = name;
    }
}

3):@PropertySource

在整个过程中第二部需要在核心配置文件当中配置那个标签,来是Spring可以读取到配置文件,但是Spring为我们提供了一个注解来替代这个配置,这个注解就叫做@PropertSource,这个注解的作用就是替换了配置文件当中的配置文件配置文件当中配置,开发步骤如下:

1:提供一个Properties和核心配置文件

2:应用@PropertySource注解(在需要注入的类上应用这个注解)

3:@Value获取值

这个注解的核心作用就是替换Spring核心配置文件当中的那个标签

@Component
@PropertySource("classpath:/init.properties")
public class Catagory {
    private Integer id;
    private String name;
    public Integer getId() {
        return id;
    }
    @Value("${id}")
    public void setId(Integer id) {
        System.out.println("Catagory.setId");
        this.id = id;
    }
    public String getName() {
        return name;
    }
    @Value("${name}")
    public void setName(String name) {
        System.out.println("Catagory.setName");
        this.name = name;
    }
}

4):@Value注意事项

1:@Value注解不能应用在静态成员变量上边,如果是静态的就不会进行注入,就不会注入,注入不上值,最终的值是null。

2:@Value注解进行注入不能注入集合形式,Map和List都不可以。以后我们遇到这个场景只有,在未来开发当中,我们Sprig提供了一种新的配置方式叫做YAML,也可以叫做Yml这种方式就可以注入的更为复杂的数据形式,这也是将来我们在学习SpringBoot当中的一种非常重要的配置方式。

总结:我们在注入方面,对于自建类型我们可以使用@Autowired进行注入,对于JDK类型提供的数据我们可以通过@Value的形式进行注入

第三章:注解扫描详解

Spring当中的注解不论是什么类型的注解想要起到对应的作用,都需要Spring能够扫描发现到,Spring扫描到之后才能基于注解的提示完成相应对象创建和注入的功能。

作为Spring框架来讲他进行包扫描的时候只需要在核心配置文件配置Componet-Scan这个标签就可以了,对应的属性base-package这个包的话指定了需要扫描的包和子包,需要注意的是进行包扫描的时候是基于当前包和子包。

但是我们说这种扫描的不太灵活,这样的比如说将在在这个扫描的下有一个类我不想让他进行扫描了,这样的话怎么办呢:

<context:Componnet-sacn base-package = "com.dashu"/>

一:排除方式

排除哪些类上的注解不进行扫描进而不创建这些类的对象

type标签Spring为我们提供了五种排查策略:

assignable:进行注解扫描的时候,排除特定类型不进行扫描。
annotation:排除特定的类不进行扫描。
aspectj:
regex:
custom:

我们使用这个exclude-filter标签进行排除操作,在排除操作当中有两个属性,这两个属性需要我们进行手动设置

<context:Component-scan base-package = "com.dashu">
  <context:exclude-filter type = "" expression = ""/>
</context:Component_scan>

1:assignable

排除特定类型(类)不进行扫描

2:annotation

排除特定注解修饰的类不进行扫描

3:aspectj

排除特点是通过切入点表达式来进行排除,排除Bean包及其子包中的所有类上上的注解不起作用。

这里的expression是切入点表达式,但是值得注意的是他在应用切入点表达式只能用包、类切入点表达式,这里可只支持这两种。这里的切入点表达式也就是表达了一个范围问题,跟Aop并没有直接的关系

应用这个切入点表达式给Spring只是一个排除范围,这样Spring在做排除工作的时候就可以排除这个范围不进行注解扫描工作,这样的话这个包中的所有的类上的注解就不会被扫描的到了。

4:regex

正则表达式

5:custom

自定义排除策略,需要自己搞,这样会在框架底层进行开发使用。例如SpringBoot底层的开发过程当中大量应用了这样的排除策略。

6:总结

1:前三种,必须要掌握,然后aspectJ是重要的

2:排除策略可以叠加使用,取得是并集

<context:component-scan base-package="com.dahsu">
  <context:exclude-filter type="assignable" expression="com.dashu.bean.User"/>
  <context:exclude-filter type="aspectj" expression="com.dashu.injection..*"/>
<context:component-scan>

二:包含方式

排除方式是排除某些类上的注解不去扫描,包含方式正好是相反的,决定了Spring需要扫描那些类的注解,包含方式决定了扫描了那些注解,完成创建。包含方式描述的就是我只想扫描包含…的类。就使用这个包含方式就对了。

与之对应的使用方式就是在于这个Componet-scan标签当中添加一个属性,所不同的事这里边引入了多了两个标签,一个是这个use-default-filters = “false”,另一个是include-filter,第一个属性来讲,他的作用是什么?

我们知道做为Spring来讲他们对应的是有自己的默认扫描策略的,默认的扫描策略就是将这个这个包和所有子包中的类进行扫描,当前包含方式,我们希望的是不是执行默认策略,而是扫描我指定的包,use-default-filters = “false”’让默认的扫描策略失效

第二个标签属性的作用就是指定扫描那些注解,type还是上边的五中策略,后边指定的范围。跟上边讲的完全一致,起到的作用完全相反。

包含的这种方式依旧可以采用叠加的这样的策略,叠加可以是不同的类型可以是相同的类型,取得是并集

四、注解开发问题

一:配置互通

作为Spring他现在创建Spring对象的时候,他实际上是由两种配置方式的,一种是注解,一种是配置文件,基于注解的配置和基于配置文件的类是可以互通的。比如我们通过@Repository创建UserDaoImpl这个类对象和基于配置文件创建UserServiceImpl这个类的的对象,在UserServiceImpl当中引用了UserDaoImpl这个类的对象,那么我们可以在Spring的配置文件当中对这个类进行注入么?肯定是可以的,被注解创建的Dao对象,是可以被注入的,只不过注入的id值要符合默认创建Dao对象的规则,使用userDaoImpl这个类就可以了。

二:何时注解何时配置文件

我们现在使用@Component注解替换了Bean标签,那我们现在是不是就不要提供配置文件了呢?当然不是的,作为基础注解,@Component @Autowired @Value只能够作为程序员开发类型的配置,只能适用于程序员开发的类型,但是此时目前的开发过程中,除了程序员字自己开发的类,还是有一些类不是自己写的比如Mybatis当中的SqlSessionFactory这个类或这MapperScannerConfigure这个类,不是我们写的,我们就没有机会在这些类上写这些注解。作为这些类我们想要创建这些类的对象,我们就只能通过Bean标签的形式。使用注解的形式只有一种,程序员开发的类上可以加上注解来创建这些类的对象,其他非程序员开发的类型时,我们还是需要Bean标签进行配置。当然,后续在Spring的高级注解当中解决了这个问题。

第五章:半注解SSM整合开发

一: 搭建开发环境

pom文件

二:引入相关配置文件

三:初始化配置

相关文章
|
2月前
|
Java Spring
【编程笔记】在 Spring 项目中使用 RestTemplate 发送网络请求
【编程笔记】在 Spring 项目中使用 RestTemplate 发送网络请求
94 0
|
3月前
|
Java 数据库连接 应用服务中间件
Spring5源码(39)-Aop事物管理简介及编程式事物实现
Spring5源码(39)-Aop事物管理简介及编程式事物实现
26 0
|
4月前
|
Java 程序员 Maven
Spring AOP入门指南:轻松掌握面向切面编程的基础知识
Spring AOP入门指南:轻松掌握面向切面编程的基础知识
|
4天前
|
XML 监控 安全
18:面向切面编程-Java Spring
18:面向切面编程-Java Spring
21 5
|
11天前
|
安全 Java Maven
[AIGC] Spring Boot中的切面编程和实例演示
[AIGC] Spring Boot中的切面编程和实例演示
|
23天前
|
Java Spring
代码优雅的转变:基于注解的AOP编程在Spring中的实践
代码优雅的转变:基于注解的AOP编程在Spring中的实践
17 0
|
23天前
|
Java Spring
切面编程的锋芒:Spring切入点的玩法与技巧
切面编程的锋芒:Spring切入点的玩法与技巧
16 0
切面编程的锋芒:Spring切入点的玩法与技巧
|
23天前
|
Java 数据库 Spring
切面编程的艺术:Spring动态代理解析与实战
切面编程的艺术:Spring动态代理解析与实战
27 0
切面编程的艺术:Spring动态代理解析与实战
|
4月前
|
XML 存储 Java
JAVAEE框架整合技术之Spring02-AOP面向切面编程技术
JAVAEE框架整合技术之Spring02-AOP面向切面编程技术
55 0
JAVAEE框架整合技术之Spring02-AOP面向切面编程技术
|
4月前
|
XML Java 数据格式
Spring 的AOP 简介,面向切面编程AOP
Spring 的AOP 简介,面向切面编程AOP
63 0