IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring-01 -> 正文阅读

[Java知识库]Spring-01

Spring

spring是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架。

userDao

package com.kang.dao;

public interface UserDao {
    void getUser();
}

userDaoImpl

package com.kang.dao;

public class UserDaoImpl implements UserDao {

    public void getUser() {
        System.out.println("userDaoImpl被调用了!");
    }

}

userService

package com.kang.service;

public interface UserService {

    void  getUser();
}

userServiceImpl

package com.kang.service;

import com.kang.dao.OrcaleUserDaoImpl;
import com.kang.dao.UserDao;
import com.kang.dao.UserDaoImpl;

public class UserServiceImpl implements UserService {

//    private UserDao userDao = new UserDaoImpl();
//    private  UserDao userDao= new OrcaleUserDaoImpl();

    private  UserDao userDao;
    //利用set进行动态实现值得注入

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }


    public void getUser() {
        userDao.getUser();
    }


}

Test

import com.kang.dao.OrcaleUserDaoImpl;
import com.kang.dao.UserDaoImpl;
import com.kang.service.UserService;
import com.kang.service.UserServiceImpl;

public class MyTest {

    public static void main(String[] args) {

        //用户实际调用的是业务层  不需要接触dao层
//        UserServiceImpl userService = new UserServiceImpl();
//        userService.getUser();

        UserServiceImpl userService = new UserServiceImpl();
        userService.setUserDao(new UserDaoImpl());

//        ((UserServiceImpl) userService).setUserDao(new UserDaoImpl());
        userService.getUser();

    }
}

  • 之前程序主动创建对象,控制权在程序员手上
  • 使用了set注入以后,程序不再具有主动性,变成了被动的接收对象

这种思想使得系统耦合性大大降低,可以更加专注于业务上的实现!这是IOC 的原型!主动权交给用户

hellospring

Hello


public class Hello {

    private String str;

    public String getStr() {
        return str;
    }

    public void setStr(String str) {
        this.str = str;
    }

    @Override
    public String toString() {
        return "Hello{" +
                "str='" + str + '\'' +
                '}';
    }

}

beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">


    <!--使用Spring来创建对象 在Spring这些都称为Bean
    类型 变量名 =  new  类型()
    Hello hello = new Hello()

    id = 变量名
    class = new 的对象
    property 相当于给对象中的属性设置一个值

    bean = 对象   new Hello()
    -->

    <bean id="hello" class="com.kang.pojo.Hello">
        <property name="str" value="我是使用了spring赋值的!"/>
    </bean>

</beans>

不需要再去程序中改动了,要实现不同的操作,只需要在xml配置文件中修改。所谓的IOC,对象由Spring来创建,管理,装配。

MysqlDaoImpl

public class MySqlDaoImpl implements UserDao {

    public void getUser() {
        System.out.println("mysql被调用了");
    }
}

UserServiceImpl

private UserDao userDao =new MySqlDaoImpl();

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void getUser() {
        userDao.getUser();
    }

    @Test
    public void testDao(){
     UserServiceImpl userService = new UserServiceImpl();
        userService.getUser();
    }


beans

 <bean id="mySqlDao" class="com.kang.dao.MySqlDaoImpl"/>
   
    <bean id="userServiceImpl" class="com.kang.service.UserServiceImpl">
        <!--ref:引用Spring容器中创建好的对象
        value: 具体的值,基本数据类型
        -->
        <property name="userDao" ref="mySqlDao"/>

    </bean>

Spring配置

别名

    <!--别名 如果添加了别名 我们也可以使用别名获取到这个对象-->
    <alias name="user" alias="userNew"/>

Bean的配置

   <!--
    id: bean的唯一标识符 相当于对象名
    class:bean对象所对应的全限定名 包名 + 类型
    name 可以同时取多个别名
    -->
    <bean id="userT" class="com.kang.pojo.UserT" name="user2">
        <constructor-arg name="name" value="555"/>
        <property name="name" value="123"/>
    </bean>

import

一般用于团队开发使用 可以将多个xml文件合并成一个

    <import resource="beans.xml"/>
    <import resource="beans2.xml"/>

依赖注入

构造器注入

基于构造器的无参构造

  1. 下表赋值
    <!--第一种 下标赋值 -->
    <bean id="user" class="com.kang.pojo.User">
        <constructor-arg index="0" value="6666"/>
    </bean>
  1. 类型
    <!--根据类型创建 不建议使用-->
    <bean id="user" class="com.kang.pojo.User">
        <constructor-arg type="java.lang.String" value="6666"/>
    </bean>
  1. 参数名
    <!--    第三种 直接通过参数名来赋值-->
    <bean id="user" class="com.kang.pojo.User">
        <constructor-arg name="name" value="666"/>
    </bean>

总结:在配置文件加载的时候,容器中管理的对象就已经初始化了。

set注入[重点]

Student.class

public class Student {

    private String name;
    private Address address;

    private String[] books;
    private List<String> hobbys;
    private Map<String, String> card;
    private Set<String> games;
    private String wife;
    private Properties info;

    public String getName() {
        return name;
    }

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <bean id="address" class="com.kang.pojo.Address">
        <property name="address" value="西安"/>
    </bean>


    <bean id="student" class="com.kang.pojo.Student">
        <!--第一种 普通值注入-->
        <property name="name" value="帅气"/>

        <!--第二种 bean注入 ref-->
        <property name="address" ref="address"/>

        <!--数组注入:ref-->
        <property name="books">
            <array>
                <value>红楼梦</value>
                <value>西游记</value>
                <value>三国演义</value>
            </array>
        </property>

        <!--list-->
        <property name="hobbys">
            <list>
                <value>听歌</value>
                <value>读书</value>
                <value>健身</value>
            </list>
        </property>

        <!--Map-->
        <property name="card">
            <map>
                <entry key="身份证" value="45446465461"/>
                <entry key="银行卡" value="43123123232341"/>
            </map>
        </property>

        <!--set-->
        <property name="games">
            <set>
                <value>LOL</value>
                <value>DNF</value>
            </set>
        </property>

        <!--null-->
        <property name="wife">
            <null/>
        </property>

        <!--property 注入   properties类继承map-->
        <property name="info">
            <props>
                <prop key="sales">sales@example</prop>
                <prop key="support">support@example.co</prop>
                <prop key="学号">20190537</prop>
                <prop key="url">dwadx2qe2dcsgfsdg</prop>
                <prop key="driver">dwdawd.dawd</prop>
            </props>
        </property>

    </bean>


</beans>

Test:

    public static void main(String[] args) {

        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Student student = (Student) context.getBean("student");
        System.out.println(student.toString());

        /*
        Student{name='帅气',
         address=Address{address='null'},
         books=[红楼梦, 西游记, 三国演义], 
         hobbys=[听歌, 读书, 健身], 
         card={身份证=45446465461, 银行卡=43123123232341}, 
         games=[LOL, DNF], 
         wife='null',
         info={学号=20190537, url=dwadx2qe2dcsgfsdg, support=support@example.co, driver=dwdawd.dawd, sales=sales@example}}
        */

    }

Bean的作用域

  1. 单例模式(singleton)Spring默认机制,只要使用同一个Bean,就只有一个对象。并发时容易有问题。

  2. 原型模式:每次从容器中get的时候,都会产生一个新的对象!

  3. 其余的request、session、application只能在web开发中用到

Bean的自动装配

  • 自动装配是spring满足bean依赖的一种方式
  • spring会在上下文中自动寻找,并自动给bean装配属性

在spring中有三种装配的方式

  1. 在xml中显示的配置
  2. 在java中显示配置
  3. 隐式的自动装配【重要】

ByName自动装配

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<!--区分大小写 大写会报错 -->
    <bean id="cat" class="com.kang.pojo.Cat"/>
    <bean id="dog" class="com.kang.pojo.Dog"/>

    <!--
    byname 会自动在容器上下文中查找和自己对象set方法后面的值对应的beanid
    -->
    <bean id="person" class="com.kang.pojo.Person" autowire="byName">
        <property name="name" value=""/>
    </bean>

</beans>

ByType自动装配


    <!--区分大小写 大写会报错 -->
    <bean id="cat" class="com.kang.pojo.Cat"/>
    <bean id="dog11" class="com.kang.pojo.Dog"/>

    <!--
    byName 会自动在容器上下文中查找,和自己对象set方法后面的值对应的beanid
    byType 会自动在容器上下文中查找,和自己对象属性类型相同的bean
    -->
    <bean id="person" class="com.kang.pojo.Person" autowire="byType">
        <property name="name" value=""/>
    </bean>
  • byname的时候,需要保证所有的bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致
  • bytype的时候,需要保证所有的bean的class唯一 ,并且这个bean需要和自动注入的属性的类型一致 (通过class=“com.kang.pojo.Person” 查找Person类下的所有对象)

使用注解实现自动装配

使用须知:

  1. 导入约束 context约束
  2. 配置注解的支持
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

</beans>

@Autowired

    @Autowired
    private Cat cat;
    @Autowired
    private Dog dog;

    private String name;

    public Cat getCat() {
        return cat;
    }

注解使用反射来实现

直接在属性上使用就可以!也可以在set方法上使用

使用Autowired可以不用编写set方法了,前提是自动装配的属性在IOC(Spring)容器中存在的。

@Autowired首先按照类型注入,如果只有一个则成功,如果是多个则再按照名称注入,找到了则成功,否则失败。

@Nullable 字段标记了这个注解,说明这个字段可以为null

@Autowired(required = false)  说明这个对象可以为空,否则不可以为空

如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解【@Autowired】完成的时候,可以使用@Qualifer(value=“xxx”)去配置@Autowired的使用,指定一个唯一的bean对象

@Resourece 默认是byName 找不到的情况下再byType

使用注解开发

使用注解开发,要保证AOP的包的导入

  1. bean
    @Compont: 组件 放在类上 说明这个类被Spring管理了 就是bean
//等价于   <bean id="user" class="com.kang.pojo.User"/>
  1. 属性的注入
    @Value 直接在属性上使用就可以!也可以在set方法上使用
<property name="name" value="123"/>
  1. 衍生的注解
    @Component 有几个衍生的注解 在web开发中 会按照mvc三层架构分层
  • dao 【@Repository】
  • service 【@Service】
  • controller 【@Controller】
    四个注解功能都是一样的 都是代表某个类注册到Spring中,装配bean
    @Scope 注解的类型
    自动装配置

小结
xml与注解:

  • xml更加万能,适用于任何场合。维护简单方便
  • 注解 不是自己的类是用不了,维护相对复杂
    xml与注解最佳实践
  • xml用来管理bean
  • 注解只负责完成属性的注入
  • 我们在使用的过程中:必须要注解生效,就需要开启注解的支持
	<!--指定要扫描的包,这个包下面的注解就会生效-->
    <context:annotation-config/>
    <context:component-scan base-package="com"/>

使用Java的方式配置Spring

现在完全不用Spring的xml配置了,全权交给java去做
JavaConfig 是Spring的一个子项目 在Spring4之后

KangConfig.class


//这个也会被Spring容器托管,注册到容器中,因为它本来就是一个@Component
// @Configuration代表这是一个配置类  类似于beans.xml
//加了路径以后 getBean可以直接使用类的名称 不开扫描 user类无法注入到容器中 容器里只有一个getUser对象
@Configuration
@ComponentScan("com.kang.pojo")
@Import(KangConfig2.class)
public class KangConfig {

    //注册一个bean 相当于我们之前写的一个bean标签
    //这个方法的名字,相当于bean标签中的id属性
    //这个方法的返回值,相当于bean标签里的class属性
    @Bean
    public User getUser() {
        return new User();//返回要注入到bean的对象
    }

}

User.class


//这个注解就是说明这个类被Spring托管了,注册到了容器之中
@Component
public class User {

    private String name;

    public String getName() {
        return name;
    }
    @Value("555")
    public void setName(String name) {
        this.name = name;
    }
}

MyTest05.class

public class MyTest05 {
    public static void main(String[] args) {

        //如果完全使用配置类的方式去做,只能通过AnnotationConfig 上下文来获取容器,通过配置类的class对象来加载
        ApplicationContext context = new AnnotationConfigApplicationContext(KangConfig.class);
        User getUser = (User)context.getBean("getUser");
        System.out.println(getUser.getName());
    }
}

代理模式

代理就是帮一些人做一些事。

代理模式是SpringAOP的底层

代理模式的分类:

  • 静态代理
  • 动态代理
    在这里插入图片描述

静态代理

角色分析:

  • 抽象角色:一般使用接口或抽象类来实现
  • 真实角色:被代理的角色
  • 代理角色 :代理真实角色,代理真实角色后,一般做一些附属操作
  • 客户:访问代理对象的人

代理模式的优点:

  • 可以使角色的操作更加纯粹,不去关注一些公共的业务
  • 公共业务交给代理模式!实现了业务的分工
  • 公共业务发生扩展的时候,方便集中管理

缺点:

  • 一个真实角色就会产生一个代理角色,代码数量翻倍,效率变低

rent 租房操作

public interface Rent {

    void rent();

}

Landlord 房东

//房东真实角色
public class Landlord implements Rent {
    public void rent() {
        System.out.println("房东要出租房子");
    }
}

Proxy 代理角色


public class Proxy {

    //多用组合 少用继承
    private Landlord landlord;

    public Proxy() {
    }

    public Proxy(Landlord landlord) {
        this.landlord = landlord;
    }


    public void rent(){
        landlord.rent();
    }

    //看房
    public void seeHouse(){
        System.out.println("中介带你看房");
    }

    //收中介费
    public void fee(){
        System.out.println("中介收中介费");
    }

}

Client 客户

public class Client {

    public static void main(String[] args) {
        Landlord landlord = new Landlord();
//        landlord.rent();

        //代理模式
        Proxy proxy = new Proxy(landlord);

        //不需要接触房东,直接找中介租房
        proxy.rent();
    }
}

静态代理示例:

UserService

public interface UserService {

    public void add();
    public void delete();
    public void update();
    public void select();

}

UserServiceImpl


public class UserServiceImpl implements UserService {
    public void add() {

        System.out.println("增加用户");
    }

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

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

    public void select() {
        System.out.println("查询用户");

    }
}

UserServiceProxy

public class UserServiceProxy implements UserService {

    private UserServiceImpl userService;

    public UserServiceImpl getUserService() {
        return userService;
    }

    public void setUserService(UserServiceImpl userService) {
        this.userService = userService;
    }

    public void add() {
        log("add");
        userService.add();
    }

    public void delete() {
        log("delete");
        userService.delete();
    }

    public void update() {
        userService.update();
    }

    public void select() {
        userService.select();
    }


    //日志方法
    public void log(String msg){
        System.out.println("使用了"+msg+"方法");
    }

    //尽量不改动以前的代码

}

Client

public class Client {

    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        
        UserServiceProxy userServiceProxy = new UserServiceProxy();
        userServiceProxy.setUserService(userService);
        
        userServiceProxy.add();
    }

}

动态代理

  • 动态代理和静态代理角色一样。
  • 动态代理的代理类是动态生成的,不是直接写好的。

动态代理分为两大类:基于接口的动态代理,基于类的动态代理

JDK提供了java.lang.reflect.InvocationHandler接口和 java.lang.reflect.Proxy类

两个类:Proxy 代理 InvocationHandler 调用处理程序

动态代理优点:

  • 可以使角色的操作更加纯粹,不去关注一些公共的业务
  • 公共业务交给代理模式!实现了业务的分工
  • 公共业务发生扩展的时候,方便集中管理
  • 一个动态代理类代理的是一个接口,一般就是对应一类业务
  • 一个动态代理类可以代理多个类,只要实现了同一个接口
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-17 21:56:42  更:2022-03-17 21:59:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:25:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码