Spring 框架学习

本文深入探讨了Spring框架的核心特性,包括IOC(控制反转)和AOP(面向切面编程)。介绍了IOC如何通过依赖注入降低耦合,如通过set方法和构造器注入,以及自动装配的byName和byType方式。此外,文章还讲解了注解在Spring中的应用,如@Autowired和@Component,以及AOP在不修改源代码情况下实现动态增强的功能,包括基于XML配置和注解实现的通知类型。
摘要由CSDN通过智能技术生成

1、Spring5-第一天


  • spring 是一个开源的免费框架
  • spring是一个轻量级、非入侵式的框架
  • 控制反转(IOC)、面向切面编程(AOP)
  • 支持事务的处理,对框架的整合

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

1.2、原来方式


  • UserDao接口–UserDaoImpl实现类
  • UserService业务接口-UserServicempl业务实现类
  • 用户实际调用的是service层,service层调用dao层

如果在dao层增加了新的方法,又想在service调用该方法,则需在service层改变代码–新建实现类

因为你在代码里面写死了,新增加一个需求,就要改一个代码,牵一发动全身

private UserDao dao=new UserDaoImpl();
private UserDao dao1=new UserDaoMySqlImpl();
public void getUser() {
    dao.getUser();
    dao1.getUser();
}

1.3、spring方式


利用set进行动态的实现注入

private UserDao dao;
public void setDao(UserDao dao) {
    this.dao = dao;
}
  • 之前,所有的东西都是由程序去进行控制创建

  • 使用set注入后,程序不在有主动性,而是被动的接收对象,把主动权交给了调用者

    我们不需要再管理对象的创建,系统的耦合性降低,可以专注于在业务的实现上–这是IOC的原型

异常:class path resource [beans.xml] cannot be opened because it does not exist

路径错误 换相对路径即可 来自源根的路径

**我们不需要再在程序中更改,要实现不同的操作,只需要在xml配置文件修改 **

IOC:对象由Spring创建,管理,装配!

  • 反转:程序本身不创建对象,而变成被动的接收对象
  • 控制:之前是程序控制创建对象,现在用spring,由spring控制
  • 依赖注入:利用set方法进行注入的(对象,成员变量)
<?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="daoImpl" class="IOC.com.xiaocong.dao.UserDaoImpl"></bean>
    <bean id="mysqlImpl" class="IOC.com.xiaocong.dao.UserDaoMySqlImpl"></bean>
    <bean id="UserServiceImpl" class="IOC.com.xiaocong.service.UserServiceImpl">
        <property name="dao" ref="mysqlImpl"></property>
    </bean>
</beans>

测试:

@Test
public void test1(){
    ApplicationContext Context= new ClassPathXmlApplicationContext("IOC\\com\\beans.xml");
    UserServiceImpl userServiceImpl = (UserServiceImpl) Context.getBean("UserServiceImpl");
    userServiceImpl.getUser();
}

1.4、IOC创建对象方式


  • 使用无参构造方法创建对象——默认
  • 使用有参构造方法创建对象——注入属性
   <bean id="user" class="xiaocong.User">

        <!--            通过有参构造方法-->
        <constructor-arg name="name" value="李四"></constructor-arg>
        <constructor-arg name="age" value="12"></constructor-arg>
    </bean>

    <bean id="userT" class="xiaocong.UserT"></bean>

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

spring会创建所有的对象(默认调用无参构造方法)

1.5、依赖注入


  • 构造器注入

    1.4

  • set方式注入

  1. set注入要求Bean提供一个默认的构造函数,并为需要注入的属性提供对应的Setter方法。

  2. Spring先调用Bean的默认构造函数实例化Bean对象,然后通过反射的方式调用Setter方法注入属性值。

  3. 假设Bean显示定义了一个带参的构造函数,则需要同时提供一个默认无参的构造函数,否则使用属性注入时将抛出异常。

<bean id="student" class="xiaocong.Students">
    <!-- 普通类型 普通注入-->
    <property name="name" value="张三"></property>
    <!-- 引用类型  bean注入-->
    <property name="address" ref="address"></property>
    <!-- 数组类型  数组注入-->
    <property name="books">
        <array>
            <value>围城</value>
            <value>白夜行</value>
        </array>
    </property>
    <!--   List注入-->
    <property name="hobbys">
        <list>
            <value>敲代码</value>
            <value>睡觉</value>
        </list>
    </property>
    <!--  Map注入-->
    <property name="card">
        <map>
            <entry key="身份证" value="000011"></entry>
            <entry key="手机号" value="1110"></entry>
        </map>
    </property>
    <!--  Set注入-->
    <property name="games">
        <set>
            <value>王者农药</value>
            <value>英雄联盟</value>
        </set>
    </property>
    <!--  null-->
    <property name="wife" value=""></property>
    <!--  properties注入-->
    <property name="info">
        <props>
            <prop key="学号">0001</prop>
            <prop key="pwd">0001</prop>
        </props>
    </property>
 </bean>
<bean id="address" class="xiaocong.Address">
<property name="address" value="江西"></property>
</bean>
private String name;
private Address address;//引用类型
private String[] books;//数组
private List<String> hobbys;
private Map<String,String> card;
private Set<String> games;
private Properties info;
private String wife;

@Override
public String toString() {
    return "Students{" +
            "name='" + name + '\'' +
            ", address=" + address.toString() +
            ", books=" + Arrays.toString(books) +
            ", hobbys=" + hobbys +
            ", card=" + card +
            ", games=" + games +
            ", info=" + info +
            ", wife='" + wife + '\'' +
            '}';
}
@Test
public void test2(){
    ApplicationContext context=new ClassPathXmlApplicationContext("bean.xml");
    Students student = (Students) context.getBean("student");
    System.out.println(student.toString());
    /**
     * Students{name='张三',
     * address=Address{address='江西'}, 对象
     * books=[围城, 白夜行],             数组
     * hobbys=[敲代码, 睡觉],            list
     * card={身份证=000011, 手机号=1110}, map
     * games=[王者农药, 英雄联盟],       set
     * info={学号=0001, pwd=0001},    properties
     * wife=''}
     */
}

2、Spring-第二天

2.1、Bean的自动装配–AutoWired

由spring帮你注入对象,不用自己手动注入(ref=id)

  • byName:会自动在容器上下文查找,和自己对象set方法后面的值对应的 bean id唯一
  • byType:会自动在容器上下文查找,和自己对象属性类型相同的 bean class,类型唯一

2.2、注解实现自动装配


  • 环境搭建(xml配置):

    1. xmlns:context=“http://www.springframework.org/schema/context”
    2. “http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd”
    3. <context:annotation-config>:注解支持
    4. 报错可能是没有导入aop jar包
    <?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 http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    
        <!--    引入注解配置-->
        <context:annotation-config></context:annotation-config>
    
        <bean id="stu11" class="IOC.com.xiaocong.pojo.Student"></bean>
        <bean id="tec" class="IOC.com.xiaocong.pojo.Teacher"></bean>
        <bean id="person" class="IOC.com.xiaocong.pojo.Person">
    <!--    通过bean id-->
    <!--    <bean id="person" class="IOC.com.xiaocong.pojo.Person" autowire="byName">-->
    
    <!--        通过bean class-->
    <!--    <bean id="person" class="IOC.com.xiaocong.pojo.Person" autowire="byType">-->
    
    <!--        set方法注入-->
    <!--        <property name="stu" ref="stu"></property>-->
    <!--        <property name="tec" ref="tec"></property>-->
    
    <!--        构造器注入-->
    <!--        <constructor-arg name="stu" ref="stu"></constructor-arg>-->
    <!--        <constructor-arg name="tec" ref="tec"></constructor-arg>-->
        </bean>
    </beans>
    
  • 直接加在属性的前面,可以不用set方法,前提是在spring容器中存在且符合id(set后面-属性)

    @@Autowried: 先根据类型(byType)注入,如果有满足的多个类型的对象,就会根据ID(byName)注入

@Autowried
private Dog dog;
@Autowried
 private Cat cat;

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

@Qualifier(value="bean id"):和@AutowWried搭配使用(有多个bean id时使用),指定唯一的bean对象注入

@Resource:类型唯一或名字唯一都可以(先通过bean id 再通过 bean class)

    @Autowired
    @Qualifier(value = "stu11")
    private Student stu;
    @Autowired
    @Qualifier(value = "tec11")
    private Teacher tec;
//    @Resource
//    private Student stu;
//    @Resource
//    private Teacher tec;

2.3、使用注解开发


<!-- 指定要扫描的包,这个包下的注解就会生效-->
<context:component-scan base-package="IOC.com.xiaocong.dao"></context:component-scan>
//等价于:<bean id="userDaoImpl" class="IOC.com.xiaocong.dao.UserDaoImpl">
//相当于new 了一个对象
@Component
public class UserDaoImpl implements UserDao{
    public void getUser() {
        System.out.println("获取用户数据");
    }
}
//    相当于<prpperty name="name" value="懒羊羊">
@Value("懒羊羊")
private String name;
public void show(){
    System.out.println("学生学习");
}

2.4、AOP 在不影响业务的情况下,实现动态的增强


  • 不通过修改源代码的方式,在主干功能中添加新的功能

  • 底层使用动态代理

  • @Test
    public void test1(){
        ApplicationContext con = new ClassPathXmlApplicationContext
                ("AOP\\com\\xiaocong\\applicationContext.xml");
        //动态代理代理的是接口
        UserService user = (UserService) con.getBean("userService");
        user.select();
    }
    

1、导包 aspectjweaver-1.9.6.jar

方法1:使用spring API接口

<!--        注册bean-->
    <bean id="userService" class="AOP.com.xiaocong.service.UserServiceImpl"></bean>
    <bean id="log" class="AOP.com.xiaocong.log.Log"></bean>
    <bean id="afterLog" class="AOP.com.xiaocong.log.AfterLog"></bean>

<!--    配置AOP-->
    <aop:config>
<!--        切入点-->
        <aop:pointcut id="pointcut" expression="execution(* AOP.com.xiaocong.service.UserServiceImpl.*(..))"/>
<!--        执行环绕增加-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"></aop:advisor>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"></aop:advisor>

    </aop:config>

2、自定义类

<bean id="diy" class="AOP.com.xiaocong.diy.DiyPointcut"> </bean>
        <aop:config>
<!--            自定义切面,ref -要引用的类-->
            <aop:aspect ref="diy">
<!--                切入点-->
                <aop:pointcut id="pointcut" expression="
                execution(* AOP.com.xiaocong.service.UserServiceImpl.*(..))"/>
<!--                通知-->
                <aop:before method="before" pointcut-ref="pointcut"></aop:before>
                <aop:after method="after" pointcut-ref="pointcut"></aop:after>
            </aop:aspect>
        </aop:config>
public class DiyPointcut {
    public void before(){
        System.out.println("++++方法执行前+++++");
    }
    public void after(){
        System.out.println("++++方法执行后+++++");
    }
}

3、注解实现

<!--            方法3:注解实现-->

    <bean id="annotationPointCut" class="AOP.com.xiaocong.diy.AnnotationPointCut"></bean>
<!--    开启注解支持-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
@Aspect//标注该类是切面
public class AnnotationPointCut {
    @Before("execution(* AOP.com.xiaocong.service.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("++++++方法执行前");
    }
    @After("execution(* AOP.com.xiaocong.service.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("+++++++++++方法执行后");
    }
    //在环绕增强中,可以给定一个参数,代表我们要获取处理切入的点
    @Around("execution(* AOP.com.xiaocong.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("环绕前------------");

        //执行方法
        Object proceed = jp.proceed();

        System.out.println("环绕后---------");

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

揽星河吖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值