小白入门基础 - Spring的Bean超详解

news2024/11/17 11:44:26

1.Spring工厂类的继承方式

从上面可以看出,创建工厂类,可以通过ClassPathXmlApplicationContext和FileSystemXmlApplicationContext这两种方式:
FileSystemXmlApplicationContext从磁盘加载配置文件,此时就需要使用绝对路径。

public void demo3(){
    //创建Spring的工厂类
    ApplicationContext applicationContext = new FileSystemXmlApplicationContext("C:\\applicationContext.xml");
    //通过工厂获得类
    UserService userService = (UserService) applicationContext.getBean("userService");
    userService.sayHello();
}

在之前老的版本中,同时通过BeanFactory来创建工厂类,这种方式虽然已经被弃用,但是依然可以使用:

@Test
public void demo4(){
    BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
    UserService userService = (UserService) beanFactory.getBean("userService");
    userService.sayHello();
}

2.Bean的实例化三种方式

(1)使用类构造器实例化

public class Bean1 {
    public Bean1(){
        System.out.println("Bean1被实例化...");
    }
}

<bean id="bean1" class="com.imooc.ioc.demo2.Bean1"></bean>

@Test
public void demo1(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    Bean1 bean1 = (Bean1) applicationContext.getBean("bean1");
}

(2)使用构造工厂实例化

public class Bean2 {
}

public class Bean2Factory {
    public static Bean2 createBean2(){
        System.out.println("Bean2Facyory方法已经执行");
        return new Bean2();
    }
}

<bean id="bean2" class="com.imooc.ioc.demo2.Bean2Factory" factory-method="createBean2"></bean>

@Test
public void demo2(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    Bean2 bean2 = (Bean2) applicationContext.getBean("bean2");
}

new ClassPathXmlApplicationContext("applicationContext.xml")会实例化applicationContext.xml配置文件中所有的构造类。

(3)使用实例工厂方法实例化

public class Bean3 {
}

public class Bean3Factory {
    public Bean3 createBean3(){
        System.out.println("Bean3Factory已经实例化");
        return new Bean3();
    }
}

<bean id="bean3Factory" class="com.imooc.ioc.demo2.Bean3Factory"/>
<bean id="bean3" factory-bean="bean3Factory" factory-method="createBean3"/>

@Test
public void demo3() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    Bean3 bean3 = (Bean3) applicationContext.getBean("bean3");
}

一般默认情况,我们会采用无参数的构造方法的方式。如果类的构造特别复杂,我们会使用第二种或者第三种方式。

3.Bean的配置

(1)id和name
  一般情况下,装配一个Bean时,通过指定一个id属性作为Bean的名称。
  id属性在IOC容器中必须是唯一的。
  如果Bean的名称中含有特殊字符,就需要使用name属性。
(2)class
  class用于设置一个类的完全路径名称,主要作用是IOC容器生成类的实例。 
(3)scope
  用于控制bean的作用域

scope常用的选项:

 request和session是针对web开发来说。

 默认采用singleton模式:

<bean id="person" class="com.imooc.ioc.demo3.Person" />

public void demo1(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    Person person1 = (Person) applicationContext.getBean("person");
    Person person2 = (Person) applicationContext.getBean("person");
    System.out.println(person1);  //com.imooc.ioc.demo3.Person@544a2ea6
    System.out.println(person2);  //com.imooc.ioc.demo3.Person@544a2ea6
}

可以看到,每次创建的对象都指向一个实例。

<bean id="person" class="com.imooc.ioc.demo3.Person" scope="prototype"/>

public void demo1(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    Person person1 = (Person) applicationContext.getBean("person");
    Person person2 = (Person) applicationContext.getBean("person");
    System.out.println(person1);  //com.imooc.ioc.demo3.Person@544a2ea6
    System.out.println(person2);  //com.imooc.ioc.demo3.Person@2e3fc542
}

如果采用prototype模式,每次都会生成一个新的对象。

4.Bean的生命周期

Spring初始化bean或销毁bean时,有时需要做一些处理工作,
因此spring可以在创建和销毁bean的时候调用bean的两个生命周期方法。
在创建的时候可以使用init-method参数来指定创建方法。
在销毁的时候可以使用destory-method参数来指定销毁方法,同时必须scope="singleton"

public class Man {
    public Man(){
        System.out.println("Man被实例化");
    }

    public void setup(){
        System.out.println("Man被初始化了");
    }

    public void teardown(){
        System.out.println("Man被销毁了");
    }
}

<bean id="man" class="com.imooc.ioc.demo3.Man" init-method="setup" destroy-method="teardown"/>

public void demo2(){
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    Man man = (Man) applicationContext.getBean("man");
    applicationContext.close();
}

打印结果:
  Man被实例化
  Man被初始化了
  Man被销毁了

5.Bean的生命周期的完整过程

(1)instantiate bean对象实例化
(2)populate properties封装属性
(3)如果Bean实现BeanNameAware执行setBeanName(获取当前类在spring中的配置名称,也就是id值)
(4)如果Bean实现BeanFactoryAware或者ApplicationContextAware,
设置工厂setBeanFactory或者上下文对象setApplicationContext。(了解工厂信息)
(5)如果存在类实现BeanPostProcessor(后处理Bean),执行postProcessBeforeInitialization
(6)如果Bean实现了InitializingBean执行afterPropertiesSet
(7)调用<bean init-method="init">指定初始化方法init
(8)如果存在类实现BeanPostProcessor(处理Bean),执行postProcessAfterInitialization
(9)执行业务处理
(10)如果Bean实现了DisposableBean执行destroy
(11)调用<bean destroy-method="customerDestroy">指定销毁方法customerDestroy,这个是用户自定义的销毁方法

<bean id="man" class="com.imooc.ioc.demo3.Man" init-method="setup" destroy-method="teardown">
    <property name="name" value="ming"/>
</bean>
<!--这个类不需要定义id,因为这是spring帮我们自动定义-->
<bean class="com.imooc.ioc.demo3.MyBeanPostProcessor"/>

package com.imooc.ioc.demo3;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class Man implements BeanNameAware, ApplicationContextAware, InitializingBean, DisposableBean {
    private String name;

    public void setName(String name) {
        System.out.println("第二步:设置属性");
        this.name = name;
    }

    public Man(){
        System.out.println("第一步:初始化...");
    }

    public void setup(){
        System.out.println("第七步:Man被初始化了");
    }

    public void teardown(){
        System.out.println("第十一步:Man被销毁了");
    }

    public void setBeanName(String s) {
        System.out.println("第三步:设置Bean的名称" + s);
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("第四步:了解工厂信息");
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("第六步:属性设置后");
    }

    public void run(){
        System.out.println("第九步:执行业务方法");
    }

    public void destroy() throws Exception {
        System.out.println("第十步:执行Spring的销毁方法");
    }
}
package com.imooc.ioc.demo3;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBeanPostProcessor implements BeanPostProcessor {
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("第五步:初始化前方法...");
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("第八步:初始化后方法...");
        return bean;
    }
}

public void demo2(){
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    Man man = (Man) applicationContext.getBean("man");
    man.run();
    applicationContext.close();
}

6.BeanPostProcessor——增强类方法

实现接口类:

public interface UserDao {
    public void findAll();

    public void save();

    public void update();

    public void delete();
}

创建实现类:

public class UserDaoImpl implements UserDao {
    public void findAll() {
        System.out.println("查询用户");
    }

    public void save() {
        System.out.println("保存用户");
    }

    public void update() {
        System.out.println("修改用户");
    }

    public void delete() {
        System.out.println("删除用户");
    }
}

调用类方法

<bean class="com.imooc.ioc.demo3.MyBeanPostProcessor"/>
<bean id="userDao" class="com.imooc.ioc.demo3.UserDaoImpl"/>

public void demo3(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserDao userDao= (UserDao)applicationContext.getBean("userDao");
    userDao.findAll();
    userDao.save();
    userDao.update();
    userDao.delete();
}

方法增强:

如果我们想增强一个方法,当然我们单独再定义一个方法,再此之前调用,
但是如果调用的次数非常多,这样就非常麻烦,这样我们可以使用BeanPostProcessor

public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
    System.out.println("第八步:初始化后方法...");
    if ("userDao".equals(beanName)){  //匹配到对应的类
        Object proxy = Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if ("save".equals(method.getName())){  //对于sava方法添加一点配置
                    System.out.println("权限校验");
                    return method.invoke(bean,args);
                }
                return method.invoke(bean,args);
            }
        });
        return proxy;
    }
    return bean;
}

7.属性注入方法及构造方法的属性注入

(1)构造方法注入

package com.imooc.ioc.demo4;

public class User {
    private String name;
    private Integer age;

    public User() {}

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

<bean id="user" class="com.imooc.ioc.demo4.User">
    <constructor-arg name="name" value="ming"/>
    <constructor-arg name="age" value="18"/>
</bean>

@Test
public void demo1(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    User user = (User) applicationContext.getBean("user");
    System.out.println(user);
}

(2)Set方法注入

  使用set方法注入,在Spring配置文件中,通过<property>设置注入的属性。

public class Person {
    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    
<bean id="person" class="com.imooc.ioc.demo4.Person">
    <property name="name" value="ming"/>
    <property name="age" value="18"/>
</bean>

public void demo1(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    Person person = (Person) applicationContext.getBean("person");
    System.out.println(person);
}

如果我现在将注入一个关联类,该如何处理了?
比如我现在给人添加一只宠物吗?

public class Cat {
    private String name;
}

public class Person {
    private String name;
    private Integer age;
    private Cat cat;
    
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", cat=" + cat.getName() +
                '}';
    }
}

在属性注入的时候,使用关联注入即可。

<bean id="person" class="com.imooc.ioc.demo4.Person">
    <property name="name" value="ming"/>
    <property name="age" value="18"/>
    <property name="cat" ref="cat"/>
</bean>
<bean id="cat" class="com.imooc.ioc.demo4.Cat">
    <property name="name" value="huahua"/>
</bean>

(3)P名称空间的属性注入

使用P命名空间。
为了简化XML文件配置,Spring从2.5开始引入一个新的P名称空间。
如果是一般属性,这样书写:
  p:<属性名>="xxx" 引入常量值
  p:<属性名>-ref="xxx"引入其他Bean对象
上面实例就可以这样些:

<bean id="person" class="com.imooc.ioc.demo4.Person" p:name="ming" p:age="18" p:cat-ref="cat"/>
<bean id="cat" class="com.imooc.ioc.demo4.Cat" p:name="huahua"/>

(4)SpEL属性注入

SpEL:spring expression language,spring表达式语言,对依赖注入进行简化的语法:#{表达式}
<bean id="" value="#{表达式}">
SpEL表达式语言:
  语法:#{}
  #{ ‘hello’ }:使用字符串
  #{beanId}:使用另一个bean
  #{beanId.content.toUpperCase()}:使用指定名属性,并使用方法
  #{T(java.lang.Math).PI}:使用静态字段或方法

创建关联类:

public class Category {
    private String name;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return name;
    }
}

创建实例类:

public class ProductInfo {
    public Double discountPrice(){
        return 188.8;
    }
}

public class Product {
    private String name;
    private Double price;
    private Category category;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public Category getCategory() {
        return category;
    }

    public void setCategory(Category category) {
        this.category = category;
    }

    @Override
    public String toString() {
        return "Product{" +
                "name='" + name + '\'' +
                ", price=" + price +
                ", category=" + category +
                '}';
    }
}

Bean管理:

<bean id="category" class="com.imooc.ioc.demo4.Category">
    <property name="name" value="#{'服装'}"/>
</bean>
<bean id="productInfo" class="com.imooc.ioc.demo4.ProductInfo"/>
<bean id="product" class="com.imooc.ioc.demo4.Product">
    <property name="name" value="#{'男装'}"/>
    <property name="price" value="#{productInfo.discountPrice()}"/>  引用工厂类的方法
    <property name="category" value="#{category}"/>
</bean>

调用:

public void demo1(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    Product product = (Product) applicationContext.getBean("product");
    System.out.println(product);
}

(5)负责类型的属性注入

数组类型的属性注入
List集合类型的属性注入
Set集合类型的属性注入
Map集合类型的属性注入
Properties类型的属性注入

创建实例类:

public class CollectionBean {
    private String[] arrs;  //数组类型
    private List<String> list;  //List集合类型
    private Set<String> set; //Set集合类型
    private Map<String,Integer> map;  //Map集合类型
    private Properties properties;  //属性类型

    public String[] getArrs() {
        return arrs;
    }

    public void setArrs(String[] arrs) {
        this.arrs = arrs;
    }

    public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public Set<String> getSet() {
        return set;
    }

    public void setSet(Set<String> set) {
        this.set = set;
    }

    public Map<String, Integer> getMap() {
        return map;
    }

    public void setMap(Map<String, Integer> map) {
        this.map = map;
    }

    public Properties getProperties() {
        return properties;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    @Override
    public String toString() {
        return "CollectionBean{" +
                "arrs=" + Arrays.toString(arrs) +
                ", list=" + list +
                ", set=" + set +
                ", map=" + map +
                ", properties=" + properties +
                '}';
    }
}

Bean管理:

<bean id="collectionBean" class="com.imooc.ioc.demo5.CollectionBean">
    <!--数组类型的属性注入-->
    <property name="arrs">
        <list>
            <value>a</value>
            <value>b</value>
            <value>c</value>
        </list>
    </property>
    <!--List集合类型的属性注入-->
    <property name="list">
        <list>
            <value>11</value>
            <value>22</value>
            <value>33</value>
        </list>
    </property>
    <!--Set集合类型的属性注入-->
    <property name="set">
        <set>
            <value>10</value>
            <value>20</value>
            <value>30</value>
        </set>
    </property>
    <!--map集合类型的属性注入-->
    <property name="map">
        <map>
            <entry key="a" value="1"></entry>
            <entry key="b" value="2"></entry>
            <entry key="c" value="3"></entry>
        </map>
    </property>
    <!--properties属性注入-->
    <property name="properties">
        <props>
            <prop key="username">ming</prop>
            <prop key="password">123456</prop>
        </props>
    </property>
</bean>

调用:

public void demo1(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    CollectionBean collectionBean = (CollectionBean) applicationContext.getBean("collectionBean");
    System.out.println(collectionBean);
    //CollectionBean{arrs=[a, b, c], list=[11, 22, 33], set=[10, 20, 30], map={a=1, b=2, c=3}, properties={password=123456, username=ming}}
}

8.Bean管理的注解方式

(1)简单使用

Spring2.5引入使用注解去定义Bean。
  @Component 描述Spring框架中Bean,这样就无需在XML文件中进行配置
除了@Component外,Spring提供了3个基本功能和@Component等效的注解:
  @Repository 用于对DAO实现类进行标注
  @Service 用于对Service实现类进行标注
  @Controller 用于对Controller实现类进行标注

比如:

import org.springframework.stereotype.Component;

@Component("userService")
public class UserService {
    public String sayHello(String name){
        return "Hello" + name;
    }
}

public void demo1(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserService userService = (UserService) applicationContext.getBean("userService");
    System.out.println(userService.sayHello("ming"));
}

注解会帮我们完成XML的Bean配置。

(2)属性注入

使用@Autowored进行自动注入
@Autowired默认按照类型进行注入
  如果存在两个相同Bean,则按照名称注入
@Autowired注入时可以针对成员变量或者set方法
通过@Autowired的required属性,设置一定要找到匹配的Bean。
使用@Qualifier指定注入Bean的名称

@Component("userService")
public class UserService {
    @Value("鱼")  //常规属性注入
    private String food;

    @Autowired  //对象注入
    private UserDao userDao;
    public String sayHello(String name){
        return "Hello" + name;
    }

    public void eat(){
        System.out.println("eat: " + food);
    }
    public void save(){
        System.out.println("Service中保存用户");
        userDao.save();  //将对象注入之后,才能调用其中的方法
    }
}

使用@Qualifier按照名称才能完成注入

@Autowired  //对象注入
@Qualifier("userDao")
private UserDao userDao;

@Resource相当于@Autowired+@Qualifier的功能。

类中如果有setter方法,那么注解需要加到setter方法上边。

(3)生命周期的注解

Spring初始化bean或销毁bean时,有时候需要一些处理工作,
因此Spring可以在创建和拆卸bean的时候,调用bean的两个生命周期方法。
那么如何使用注解的方式来完成了?
init-method初始化的时候,可以用@PostConstruct来代替。
destory-method销毁对象时,可以使用@PreDestroy

@Component("bean1")
public class Bean1 {
    @PostConstruct
    public void init(){
        System.out.println("initBean...");
    }

    public void say(){
        System.out.println("say...");
    }

    @PreDestroy
    public void destory(){
        System.out.println("destroyBean...");
    }
}

public void demo2() {
    ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    Bean1 bean1 = (Bean1) classPathXmlApplicationContext.getBean("bean1");
    bean1.say();
    classPathXmlApplicationContext.close();
}

(4)注入范围的注解

使用注解配置的Bean和<bean>配置的一样,默认作用范围都是singleton。
使用@Scope注解用于指定Bean的作用范围。

@Component("bean2")
public class Bean2 {
}

public void demo2() {
    ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    Bean2 bean1 = (Bean2) classPathXmlApplicationContext.getBean("bean2");
    Bean2 bean2 = (Bean2) classPathXmlApplicationContext.getBean("bean2");
    System.out.println(bean1);  //com.imooc.demo2.Bean2@79ca92b9
    System.out.println(bean2);  //com.imooc.demo2.Bean2@79ca92b9
}

如果指定作用范围:

@Component("bean2")
@Scope("prototype")
public class Bean2 {
}

结果将完全不同:

public void demo2() {
    ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    Bean2 bean1 = (Bean2) classPathXmlApplicationContext.getBean("bean2");
    Bean2 bean2 = (Bean2) classPathXmlApplicationContext.getBean("bean2");
    System.out.println(bean1);  //com.imooc.demo2.Bean2@1198b989
    System.out.println(bean2);  //com.imooc.demo2.Bean2@7ff95560
}

9.传统XML配置和注解整合开发

XML方式的优势:
  结构清晰,易于阅读
注解方式的优势:
  开发便捷,属性注入方便

XML与注解和整合开发
  1.引入context命名空间
  2.在配置文件中添加context:annotation-config标签

(1)传统方式

public class CategoryDao {
    public void save(){
        System.out.println("CategoryDao中sava方法执行了");
    }
}
public class ProductDao {
    public void save(){
        System.out.println("ProductDao中sava方法执行了");
    }
}

public class ProductService {
    private CategoryDao categoryDao;
    private ProductDao productDao;

    public CategoryDao getCategoryDao() {
        return categoryDao;
    }

    public void setCategoryDao(CategoryDao categoryDao) {
        this.categoryDao = categoryDao;
    }

    public ProductDao getProductDao() {
        return productDao;
    }

    public void setProductDao(ProductDao productDao) {
        this.productDao = productDao;
    }

    public void save(){
        System.out.println("ProductService的save方法");
        categoryDao.save();
        productDao.save();
    }
}

<bean id="productService" class="com.imooc.demo3.ProductService">
    <property name="categoryDao" ref="categoryDao"/>
    <property name="productDao" ref="productDao"/>
</bean>
<bean id="categoryDao" class="com.imooc.demo3.CategoryDao"/>
<bean id="productDao" class="com.imooc.demo3.ProductDao"/>

public void demo1(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    ProductService productService = (ProductService) applicationContext.getBean("productService");
    productService.save();
}

(2)混合开发

如果此时属性注入想使用注解方式,那么可以这样:

<context:annotation-config/>
<bean id="productService" class="com.imooc.demo3.ProductService">
</bean>
<bean id="categoryDao" class="com.imooc.demo3.CategoryDao"/>
<bean id="productDao" class="com.imooc.demo3.ProductDao"/>

public class ProductService {
    @Resource(name="categoryDao")  //属性注入
    private CategoryDao categoryDao;
    @Resource(name="productDao")
    private ProductDao productDao;

    public void save(){
        System.out.println("ProductService的save方法");
        categoryDao.save();
        productDao.save();
    }
}

public void demo1(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    ProductService productService = (ProductService) applicationContext.getBean("productService");
    productService.save();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1363432.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024跨境电商测评还能做吗?

基本上做跨境电商这块的都做过测评 原因也很简单&#xff0c;一方面review是产品转化率的重要保证&#xff0c;另一方面一个好的测评订单也可以有效的提升产品的关键词排名和点击率转化率 为什么说现在找测评是越来越难了呢 大环境因素是亚马逊卖家越来越多了&#xff0c;内…

ShardingSphere-JDBC学习笔记

引言 开源产品的小故事 Sharding-JDBC是2015年开源的&#xff0c;早期的定位就是一个分布式数据库的中间件&#xff0c;而在它之前有一个MyCat的产品。MyCat也是从阿里开源出来的&#xff0c;作为分库分表的代名词火了很长一段时间&#xff0c;而MyCat早年的目标就是想进入ap…

云计算:OpenStack 分布式架构管理VXLAN网络(单控制节点与多计算节点)

目录 一、实验 1.环境 2.各节点新增网卡准备VXLAN网络 3.控制节点配置私有网络 4.计算节点1配置私有网络 5.计算节点2配置私有网络 6.重启服务 7.修改Dashboard 8.新建项目&#xff08;租户&#xff09;及用户 9.新建网络与子网 10.新建实例 11.新建路由 12.新增浮…

使用PyTorch实现去噪扩散模型

在深入研究去噪扩散概率模型(DDPM)如何工作的细节之前&#xff0c;让我们先看看生成式人工智能的一些发展&#xff0c;也就是DDPM的一些基础研究。 VAE VAE 采用了编码器、概率潜在空间和解码器。在训练过程中&#xff0c;编码器预测每个图像的均值和方差。然后从高斯分布中对…

用友NC word.docx 任意文件读取漏洞复现

0x01 产品简介 用友NC是一款企业级ERP软件。作为一种信息化管理工具,用友NC提供了一系列业务管理模块,包括财务会计、采购管理、销售管理、物料管理、生产计划和人力资源管理等,帮助企业实现数字化转型和高效管理。 0x02 漏洞概述 用友NC 系统word.docx等接口存在任意文件…

Java调用shell脚本实现数据库备份功能

本篇文章主要介绍怎样使用Java程序&#xff0c;执行服务器上的数据库备份Shell脚本进行MySQL数据库的备份功能。 学习目标 使用Java执行Shell脚本、实现MySQL数据库的备份功能。 学习内容 编写导出MysSQL数据库的Shell脚本 以下是一个使用Bash脚本进行数据库备份的示例代码…

每天刷两道题——第七天+第八天

力扣官网 1.1移动零 给定一个数组 n u m s nums nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序&#xff0c;在不复制数组的情况下原地对数组进行操作。 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0] 代码 def moveZeroea…

分布式锁3: zk实现分布式锁4 使用临时顺序节点+watch监听+可重入(threadLocal)

一 zk实现分布式锁的可重入性 1.1 使用ThreadLocal属性 引入ThreadLocal线程局部变量保证zk分布式锁的可重入性。 1.2 关键代码说明 1.3 代码 1.3.1 初始化客户端 1.3.2 分布式锁代码 package com.atguigu.distributed.lock.config;import com.baomidou.mybatisplus.core…

Docker学习与应用(六)-Docker网络

1、Docker网络 Docker有多种网络模式可以选择&#xff0c;可以根据应用场景和需求选择合适的网络模式。 桥接模式&#xff08;Bridge Mode&#xff09;&#xff1a;默认情况下&#xff0c;Docker使用桥接模式创建一个虚拟网络&#xff0c;所有容器会连接到这个虚拟网络中。每个…

PPT模板(100套IT科技互联网风)

哈喽&#xff0c;小伙伴们&#xff0c;最近是不是都在准备年终总结、年终述职&#xff0c;一个好的PPT模板是编写报告的开端。我最近也在准备年终总结报告&#xff0c;一块整理了一些PPT模板。这些模板适用于各种IT科技互联网相关的场合&#xff0c;如产品发布会、项目提案、工…

TypeScript基础(一)基本类型与类型运算

✨ 专栏介绍 TypeScript是一种由微软开发的开源编程语言&#xff0c;它是JavaScript的超集&#xff0c;意味着任何有效的JavaScript代码都是有效的TypeScript代码。TypeScript通过添加静态类型和其他特性来增强JavaScript&#xff0c;使其更适合大型项目和团队开发。 在TypeS…

C#,入门教程(11)——枚举(Enum)的基础知识和高级应用

上一篇&#xff1a; C#&#xff0c;入门教程(10)——常量、变量与命名规则的基础知识https://blog.csdn.net/beijinghorn/article/details/123913570 不会枚举&#xff0c;就不会编程&#xff01; 枚举 一个有组织的常量系列 比如&#xff1a;一个星期每一天的名字&#xf…

【SpringCloud】之入门级及nacos的集成使用

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《SpringCloud开发之入门级及nacos》。&#x1f3…

k8s 陈述式资源管理

k8s 陈述式资源管理 命令行&#xff1a;kubectl命令行工具 优点&#xff1a;90%以上的场景都可以满足 对资源的增&#xff0c;删&#xff0c;查比较方便&#xff0c;对改不是很友好 缺点&#xff1a; 命令比较冗长&#xff0c;复杂难记 声明式&#xff1a; k8s当中的yaml…

SpringCloud-高级篇(十二)

在主从集群中slave节点发生了宕机&#xff0c;不用担心&#xff0c;只要它重启就能从master节点上完成数据的同步&#xff0c;恢复数据&#xff0c;如果宕机的不是slave而是master&#xff0c;是不是master重启就可以呢&#xff1f;如果你做了master节点的数据持久化&#xff0…

SolidUI Gitee GVP

感谢Gitee&#xff0c;我是一个典型“吃软不吃硬”的人。奖励可以促使我进步&#xff0c;而批评往往不会得到我的重视。 我对开源有自己独特的视角&#xff0c;我只参与那些在我看来高于自身认知水平的项目。 这么多年来&#xff0c;我就像走台阶一样&#xff0c;一步一步参与…

MySQL第四战:视图以及常见面试题(上)

目录 目录&#xff1a; 一.视图 1.介绍什么是视图 2.视图的语法 语法讲解 实例操作 二.MySQL面试题 1.SQL脚本 2.面试题实战 三.思维导图 目录&#xff1a; 随着数字化时代的飞速发展&#xff0c;数据库技术&#xff0c;特别是MySQL&#xff0c;已经成为IT领域中不可…

自动驾驶:低阶可部署的单目测距算法-基于YOLO与透视变换

一、开发环境 部署平台&#xff1a;英伟达的Jetson Nano 环境&#xff1a;Linux ROS 语言&#xff1a;C 设备&#xff1a;1920*1080像素的摄像头、开发板。 模型&#xff1a;yolo-v8s 二、单目测距实现思路 0、标定相机和车辆&#xff08;假设已经标定完成&#xff09; 1、通…

配置cendos 安装docker 配置阿里云国内加速

由于我安装的cendos是镜像版。已经被配置好了。所以只需要更新相关配置信息即可。 输入 yum update自动更新所有配置 更新完成后输入 yum list docker-ce --showduplicates | sort -r 自动查询所有可用的docker版本 输入 yum install docker-ce docker-ce-cli container…

【Nginx】#安装配置及应用场景使用说明

文章目录 常见公网DNS服务1.Nginx的安装版本区别解压文件1.1编译安装1.2 启动安装1.3 安装成系统服务 2.运行原理3.Nginx配置及应用场景3.1最小配置worker_processesworker_connectionsinclude mime.types;default_type application/octet-stream;sendfifile on;keepalive_time…