Spring Boot 注解 常用注解说明

Spring Boot是一个快速开发框架,快速的将一些常用的第三方依赖整合(通过Maven子父亲工程的方式),简化xml配置,全部采用注解形式,内置Http服务器(Jetty和Tomcat),最终以Java应用程序进行执行。Spring DIP

一、注解Controller 和 RestController

RestController的作用相当于Controller加ResponseBody共同作用的结果,但采用RestController请求方式一般会采用Restful风格的形式。

Controller的作用:声明该类是Controller层的Bean,将该类声明进入Spring容器中进行管理

ResponseBody的作用:表明该类的所有方法的返回值都直接进行提交而不经过视图解析器,且返回值的数据自动封装为json的数据格式

RestController的作用:包含上面两个的作用,且支持Restful风格的数据提交方式

Restful风格:

    get:获取数据时用的请求方式

    post:增加数据时的请求方式

    put:更新数据时的请求方式

    delete:删除数据时的请求方式

在每个Controller类的上边加速注解,用于形成API接口交付给前端

二、@NoArgsConstructor、@AllArgsConstructor、@RequiredArgsConstructor

区别:

  • @NoArgsConstructor:生成无参的构造方法。
  • @AllArgsConstructor:生成该类下全部属性的构造方法。
  • @RequiredArgsConstructor:生成该类下被final修饰或者non-null字段生成一个构造方法。

场景:

在springboot中,对于一个bean类,注入其他bean的时候,常见的是使用@Autowired,实际上也可以使用构造函数注入,
这个时候就可以使用@AllArgsConstructor或者@RequiredArgsConstructor来代替。

三、泛型

以下代码编译器会报错(com.yang.memorytest.Person.this’ cannot be referenced from a static context),因为泛型类型只有在类实例化的时候才确定,而静态方法可以直接通过类来调用;

如果静态方法需要使用泛型,可以在方法定义泛型,

    public class Person {    
        public static <T>void a(T data){        
        }
    }
    public static <T> Result<T> sucess(){
        return new Result<>(20008, "sucess", null);
    }

四、@Resource @Autowired

spring的管理机制Bean工厂已经把对象创建好了 你只需要调用就行!

一般代码中对象普遍是new Class把对象实例出来,注入之后呢,spring帮你new好了,你可以直接用了

@Resource主要做依赖注入,从容器中自动获取bean,作用如下:

在启动Spring时,首先要启动容器
在启动Sprng容器时,会默认寻找容器扫描范围内的可加载的bean,然后查找哪些bean上的属性和方法有@resource注解
找到@resource注解后,判断其name属性是否为空,若为空,看Spring容器中的bean中的id与@resource要注解的那个变量属性名是否相同,如相同,匹配成功;如不同,看spring容器中bean的id对应的类型是否与@resource要注解的那个变量属性对应的类型是否相等,若相等,匹配成功,若不相等,匹配失败
如果@resource注解括号中的name属性不为空,看name的属性值和容器中的bean的id名是否相等,如相等,则匹配成功,如果不相等,则匹配失败

@Resource和@Autowired注解都是用来实现依赖注入的。只是@Autowired按by type自动注入,而@Resource默认按by name自动注入

@Autowired 和 @Resource 都是用来实现依赖注入的注解(在 Spring/Spring Boot 项目中),但二者却有着 5 点不同:

来源不同:@Autowired 来自 Spring 框架,而 @Resource 来自于(Java)JSR-250;
依赖查找的顺序不同:@Autowired 先根据类型再根据名称查询,而 @Resource 先根据名称再根据类型查询;
支持的参数不同:@Autowired 只支持设置 1 个参数,而 @Resource 支持设置 7 个参数;
依赖注入的用法支持不同:@Autowired 既支持构造方法注入,又支持属性注入和 Setter 注入,而 @Resource 只支持属性注入和 Setter 注入;
编译器 IDEA 的提示不同:当注入 Mapper 对象时,使用 @Autowired 注解编译器会提示错误,而使用 @Resource 注解则不会提示错误。

https://www.jb51.net/article/260980.htm

五、@Component和@Bean

  1. @Component 和 @Bean 是两种使用注解来定义bean的方式。

  2. @Component(和@Service和@Repository)用于自动检测和使用类路径扫描自动配置bean。注释类和bean之间存在隐式的一对一映射(即每个类一个bean)。这种方法对需要进行逻辑处理的控制非常有限,因为它纯粹是声明性的。

  3. @Bean用于显式声明单个bean,而不是让Spring像上面那样自动执行它。它将bean的声明与类定义分离,并允许您精确地创建和配置bean。

  4. @Bean则常和@Configuration注解搭配使用

    1.Component注解表明一个类会作为组件类,并告知Spring要为这个类创建bean。
    
    2.Bean注解告诉Spring这个方法将会返回一个对象,这个对象要注册成Spring应用上下文中的bean。通常方法体包含了最终产生bean实例的逻辑。
  5. @Autowired或者@Resource注解注入

  6. 为什么有了@Compent,还需要@Bean呢?

    如果想将第三方的类变成组件,你又没有没有源代码,也就没办法使用@Component进行自动配置,这种时候使用@Bean就比较合适了。不过同样的也可以通过xml方式来定义。
    
    另外@Bean注解的方法返回值是对象,可以在方法中为对象设置属性。
    
    另外了解一下Spring的Starter机制,就是通过@Bean注解来定义bean。可以搭配@ConditionalOnMissingBean注解 
    
    @ConditionalOnMissingClass注解,如果本项目中没有定义该类型的bean则会生效。避免在某个项目中定义或者通过congfig注解来声明大量重复的bean。

区别:

- Component通常是通过类路径扫描来自动侦测以及自动装配到Spring容器中
- Bean注解通常是我们在标有该注解的方法中定义产生这个bean的逻辑。
- Component用在类上,Bean用在方法上。

Spring DIP 依赖倒置原则

springboot中文社区

一、java 基础

在Java中,定义方法返回值为接口类型,需要实现该接口的具体实现类,并在方法中返回该实现类的实例对象。

例如,定义一个方法返回值为List接口类型,可以通过以下方式实现:

public List<String> getList() {
    List<String> list = new ArrayList<>();
    // add elements to the list
    return list;
}

在这个例子中,实现了List接口的具体实现类ArrayList,并在getList方法中返回了ArrayList的实例对象。由于ArrayList实现了List接口,因此可以将其作为List类型的返回值。

当调用该方法时,可以使用List类型来接收返回值:

List<String> result = getList();

这样做的好处是,如果后续需要修改返回值的类型,只需要修改返回的实现类即可,而无需修改调用该方法的代码。同时,使用接口作为返回类型也符合面向对象编程的原则,提高了代码的可扩展性和可维护性。

二、Spring 中如何注入Bean

在Spring中,可以使用@Autowired或@Resource注解来注入返回值类型是接口的Bean。

例如,定义一个接口UserService:

    public interface UserService {
        void addUser(User user);
        User getUserById(int id);
    }

然后有一个实现类UserServiceImpl:

    @Service
    public class UserServiceImpl implements UserService {
        // ...
    }

使用@Autowired注解来注入UserService:

@Service
public class SomeService {
    @Autowired
    private UserService userService;
    // ...
}

使用@Resource注解来注入UserService:

@Service
public class SomeService {
    @Resource
    private UserService userService;
    // ...
}

需要注意的是,如果有多个实现类实现了同一个接口,需要使用@Qualifier注解来指定注入的实现类。例如:

@Service
public class SomeService {
    @Autowired
    @Qualifier("userServiceImpl2")
    private UserService userService;
    // ...
}

三、针对接口编程

针对接口编程而不是具体实现类,是一种编程思想,也是面向对象编程的核心原则之一——依赖倒置原则(DIP)。这种编程方式可以使代码更加灵活、可扩展、易于维护。

在 Java 中,可以使用接口作为方法参数、返回值或成员变量的类型,从而实现针对接口编程而不是具体实现类。下面是一个简单的例子:

假设有一个接口 Animal 和两个实现类 Dog 和 Cat:

public interface Animal {
    public void makeSound();
}

public class Dog implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Wang Wang!");
    }
}

public class Cat implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Miao Miao!");
    }
}

现在我们需要一个方法来处理动物的声音,但是我们不确定传入的具体是什么动物,这时候我们可以使用 Animal 接口来作为参数类型:

public class AnimalSound {
    public void makeSound(Animal animal) {
        animal.makeSound();
    }
}

这样,无论传入的是 Dog 还是 Cat,都可以正确输出声音。

使用接口编程还有一个好处是,可以方便地实现依赖注入。比如,我们有一个使用 Animal 接口作为参数类型的类:

public class AnimalService {
    private Animal animal;

    public AnimalService(Animal animal) {
        this.animal = animal;
    }

    public void makeSound() {
        animal.makeSound();
    }
}

使用 Spring 容器进行依赖注入时,只需要将具体的实现类配置为 Bean,然后在 AnimalService 中使用 @Autowired 注解注入即可:

@Configuration
public class AppConfig {
    @Bean
    public Animal dog() {
        return new Dog();
    }

    @Bean
    public AnimalService animalService(Animal animal) {
        return new AnimalService(animal);
    }
}

这样,无论是注入 Dog 还是 Cat,都可以正确输出声音。同时,如果需要新增一种动物实现,只需要实现 Animal 接口,并将其配置为 Bean 即可,不需要修改 AnimalService 类的代码。这就体现了针对接口编程而不是具体实现类的优势。

四、具体实例

有这样一个类

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class MySecurity {
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

这段代码是一个Spring的配置类,使用@Configuration注解标记,表示这是一个Java配置文件。

其中@Bean注解用于声明一个方法,这个方法返回一个PasswordEncoder类型的对象,并且这个对象会交给Spring容器管理,可以被其他组件注入使用。

具体来说,这段代码中声明了一个名为passwordEncoder的Bean,这个Bean的类型是PasswordEncoder,返回的是一个BCryptPasswordEncoder对象。BCryptPasswordEncoder是Spring Security提供的一种密码加密工具,用于对用户密码进行加密处理。

这个Bean的作用是在Spring Security中使用加密功能时提供PasswordEncoder实例,可以通过在其他组件中使用@Autowired注解来引用这个Bean,从而使用BCryptPasswordEncoder对密码进行加密处理。

假设我们需要在一个服务类中使用 PasswordEncoder 接口,可以使用 Spring 的依赖注入来获取该接口的实例。假设服务类的名称为 MyService,注入过程如下:

import org.springframework.security.crypto.password.PasswordEncoder;

@Service
public class MyService {
    @Autowired
    private PasswordEncoder passwordEncoder;

    // 其他代码
}

已经在Spring容器中定义了一个实现PasswordEncoder接口的Bean。在代码中使用@Autowired注解进行自动注入时,Spring会自动查找容器中是否有符合类型的Bean,然后注入到对应的字段中。因此,如果MySecurity配置类中定义了一个返回值类型为PasswordEncoder的Bean,并且该类被正确扫描到并加载到Spring容器中,那么在其他需要使用该Bean的地方,可以使用@Autowired进行自动注入。

虽然PasswordEncoder是一个接口,但是在MySecurity配置类中,使用@Bean注解定义了一个passwordEncoder()方法并返回了一个实现了PasswordEncoder接口的BCryptPasswordEncoder对象。这样在Spring容器启动时会创建该对象并将其注册到容器中,因此在其他需要使用PasswordEncoder的地方,可以通过@Autowired注解将其注入进去,实际上注入的是BCryptPasswordEncoder对象。这也是Spring中面向接口编程的一个重要原则:针对接口编程而不是具体实现类。

CSS3 3D转换

1 .三维坐标系

三维坐标系其实就是指立体空间,立体空间是由3个轴共同组成的。

x轴:水平向右 注意: x 右边是正值,左边是负值 \n  y轴:垂直向下 注意: y 下面是正值,上面是负值\n  z轴:垂直屏幕 注意: 往外面是正值,往里面是负值

3D 转换主要学习工作中最常用的 3D 位移 和 3D 旋转

主要知识点

  • 3D位移: translate3d(x,y,z)
  • 3D旋转: rotate3d(x,y,z)
  • 透视: perspective
  • 3D呈现 transfrom-style

1.2 3D移动 translate3d

3D移动在2D移动的基础上多加了一个可以移动的方向,就是z轴方向。

1>translform:translateX(100px):仅仅是在x轴上移动\n    2>translform:translateY(100px):仅仅是在Y轴上移动\n  3>translform:translateZ(100px):仅仅是在Z轴上移动(注意:translateZ一般用px单位)

4>transform:translate3d(x,y,z):其中 x、y、z 分别指要移动的轴的方向的距离

因为z轴是垂直屏幕,由里指向外面,所以默认是看不到元素在z轴的方向上移动

1.3 透视 perspective

在2D平面产生近大远小视觉立体,但是只是效果二维的

1>如果想要在网页产生3D效果需要透视(理解成3D物体投影在2D平面内)。

2>模拟人类的视觉位置,可认为安排一只眼睛去看

3>透视我们也称为视距:视距就是人的眼睛到屏幕的距离

4>距离视觉点越近的在电脑平面成像越大,越远成像越小

5>透视的单位是像素

透视写在被观察元素的父盒子上面的

d:就是视距,视距就是一个距离人的眼睛到屏幕的距离。

z:就是 z轴,物体距离屏幕的距离,z轴越大(正值) 我们看到的物体就越大。

1 .4 translateZ

translform:translateZ(100px):仅仅是在Z轴上移动。\n   有了透视,就能看到translateZ 引起的变化了

1>translateZ:近大远小

2>translateZ:往外是正值

3>translateZ:往里是负值

1.5 3D旋转 rotate3d

3D旋转指可以让元素在三维平面内沿着 x轴,y轴,z轴或者自定义轴进行旋转。

语法

  1. transform:rotateX(45deg):沿着x轴正方向旋转 45度
  2. transform:rotateY(45deg) :沿着y轴正方向旋转 45deg\n
  3. transform:rotateZ(45deg) :沿着Z轴正方向旋转 45deg
  4. transform:rotate3d(x,y,z,deg): 沿着自定义轴旋转 deg为角度(了解即可)

左手准则

判断X轴正负值

左手的手拇指指向 x轴的正方向\n  其余手指的弯曲方向就是该元素沿着x轴旋转的方向

判断Y轴正负值

左手的手拇指指向 y轴的正方向\n  其余手指的弯曲方向就是该元素沿着y轴旋转的方向(正值)

transform:rotate3d(x,y,z,deg): 沿着自定义轴旋转 deg为角度(了解即可)\nxyz是表示旋转轴的矢量,是标示你是否希望沿着该轴旋转,最后一个标示旋转的角度。

1>transform:rotate3d(1,0,0,45deg) 就是沿着x轴旋转 45deg

2>transform:rotate3d(1,1,0,45deg) 就是沿着对角线旋转 45deg

1.6 3D呈现 transfrom-style

控制子元素是否开启三维立体环境。。

  • transform-style: flat 子元素不开启3d立体空间 默认的
  • transform-style: preserve-3d; 子元素开启立体空间
  • 代码写给父级,但是影响的是子盒子\n  这个属性很重要,后面必用

案例:两面翻转的盒子

<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\">\n    <title>Document</title>\n    <style>\n        body {\n            perspective: 400px;\n        }\n        \n        .box {\n            position: relative;\n            width: 300px;\n            height: 300px;\n            margin: 100px auto;\n            transition: all .4s;\n            /* 让背面的紫色盒子保留立体空间 给父级添加的 */\n            transform-style: preserve-3d;\n        }\n        \n        .box:hover {\n            transform: rotateY(180deg);\n        }\n        \n        .front,\n        .back {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            border-radius: 50%;\n            font-size: 30px;\n            color: #fff;\n            text-align: center;\n            line-height: 300px;\n        }\n        \n        .front {\n            background-color: pink;\n            z-index: 1;\n        }\n        \n        .back {\n            background-color: purple;\n            /* 像手机一样 背靠背 旋转 */\n            transform: rotateY(180deg);\n        }\n    </style>\n</head>\n\n<body>\n    <div class=\"box\">\n        <div class=\"front\">快乐是我的</div>\n        <div class=\"back\">也是你的</div>\n    </div>\n</body>\n\n</html>

案例:3D导航栏

<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\">\n    <title>Document</title>\n    <style>\n        * {\n            margin: 0;\n            padding: 0;\n        }\n        \n        ul {\n            margin: 100px;\n        }\n        \n        ul li {\n            float: left;\n            margin: 0 5px;\n            width: 120px;\n            height: 35px;\n            list-style: none;\n            /* 一会我们需要给box 旋转 也需要透视 干脆给li加 里面的子盒子都有透视效果 */\n            perspective: 500px;\n        }\n        \n        .box {\n            position: relative;\n            width: 100%;\n            height: 100%;\n            transform-style: preserve-3d;\n            transition: all .4s;\n        }\n        \n        .box:hover {\n            transform: rotateX(90deg);\n        }\n        \n        .front,\n        .bottom {\n            position: absolute;\n            left: 0;\n            top: 0;\n            width: 100%;\n            height: 100%;\n        }\n        \n        .front {\n            background-color: pink;\n            z-index: 1;\n            transform: translateZ(17.5px);\n        }\n        \n        .bottom {\n            background-color: purple;\n            /* 这个x轴一定是负值 */\n            /* 我们如果有移动 或者其他样式,必须先写我们的移动 */\n            transform: translateY(17.5px) rotateX(-90deg);\n        }\n    </style>\n</head>\n\n<body>\n    <ul>\n        <li>\n            <div class=\"box\">\n                <div class=\"front\">快乐是我的</div>\n                <div class=\"bottom\">也是你的</div>\n            </div>\n        </li>\n        <li>\n            <div class=\"box\">\n                <div class=\"front\">快乐是我的</div>\n                <div class=\"bottom\">也是你的</div>\n            </div>\n        </li>\n        <li>\n            <div class=\"box\">\n                <div class=\"front\">快乐是我的</div>\n                <div class=\"bottom\">也是你的</div>\n            </div>\n        </li>\n        <li>\n            <div class=\"box\">\n                <div class=\"front\">快乐是我的</div>\n                <div class=\"bottom\"也是你的</div>\n            </div>\n        </li>\n        <li>\n            <div class=\"box\">\n                <div class=\"front\">快乐是我的</div>\n                <div class=\"bottom\">也是你的</div>\n            </div>\n        </li>\n        <li>\n            <div class=\"box\">\n                <div class=\"front\">快乐是我的</div>\n                <div class=\"bottom\">也是你的</div>\n            </div>\n        </li>\n    </ul>\n</body>\n\n</html>