Spring框架官网学习内容(不太好找)

小知识点:

一、required

1、@Autowired(required = false)

说明对象可以为null,否则不可以为空。默认required=true。

理解:当required=false时,该属性在spring中可以为没有注册的状态,且打印该属性为null。

如果required=true时,该属性在spring中不可以为没有注册的状态,运行时报错。

具体测试代码:

测试方案,Cat类,TestDao类中包含Car类,Test类执行

1、required=true的情况

Cat类

package com.qian.pojo;

public class Cat {
    private String name;

    public String getName() {
        return name;
    }

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

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

TestDao类

package com.qian.dao;

import com.qian.pojo.Cat;
import org.springframework.beans.factory.annotation.Autowired;

public class testDao {
    @Autowired    //默认即为required=true
    private Cat cat;

    public Cat getCat() {
        return cat;
    }
}

测试类

package com.qian.service;

import com.qian.dao.testDao;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ServiceTest {

    public static  void  main(String[] args){
        //获取ApplicationContext,拿到Spring的容器,通过配置文件获取
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        //容器在手,天下我有,需要什么,就直接get什么
        testDao testDao = context.getBean("testDao", testDao.class);
        System.out.println(testDao.getCat());

    }

}

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"
       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/>

    <bean name="testDao" class="com.qian.dao.testDao" >
    </bean>

</beans>

测试结果报错

spring leader选主 spring require_xml

2、required=false的情况

TestDao变化外,其余不变

package com.qian.dao;

import com.qian.pojo.Cat;
import org.springframework.beans.factory.annotation.Autowired;

public class testDao {
    @Autowired(required = false)
    private Cat cat;

    public Cat getCat() {
        return cat;
    }
}

演示结果:

spring leader选主 spring require_spring_02

二、qualifier  配合autowired使用

autowired是通过类型来进行类的装配

<bean name="testDao" class="com.qian.dao.testDao" >
    </bean>

其中name为名,class为类型

因此,当同一个class中有两个bean在spring容器中被注册时,会报错(奇怪的当其中第一个bean的name为类名的小写时,此情况并不会报错) 

XML文件如下

<bean name="dog2" class="com.qian.pojo.Cat" >
        <property name="name" value="001"></property>
    </bean>

    <bean name="dog" class="com.qian.pojo.Cat" >
        <property name="name" value="002"></property>
    </bean>

    <bean name="testDao" class="com.qian.dao.testDao" >
    </bean>

报错如下:

spring leader选主 spring require_spring leader选主_03

解决方案:加qualifier

package com.qian.dao;

import com.qian.pojo.Cat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

public class testDao {
    @Autowired
    @Qualifier(value = "dog")   //解决方案在此
    private Cat cat;

    public Cat getCat() {
        return cat;
    }
}

三、Resource  

Resource先找name,再找类型。功能上等于autowired和qualifier

四、Value 注入元素

联合@component联用

package com.qian.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class Cat {
    @Value("张三")     //此处name将等于"张三"
    private String name;

    public String getName() {
        return name;
    }

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

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

五、@scope(value = "prototype")   用在component下方

package com.qian.dao;

import com.qian.pojo.Cat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope(value = "prototype")
public class testDao {
    @Autowired
    private Cat cat;

    public Cat getCat() {
        return cat;
    }
}

六、Configuration   配置类

注释为重点内容,配置类配置的是spring!!!

package com.qian.config;

import com.qian.dao.TestDao;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

//这个也会Spring容器托管,注册到容器中,因为他本来就是一个@Component
//@Configuration代表这是一个配置类,等同于我们之前写的Application.xml
@Configuration
@ComponentScan("com.qian")   //可以写扫描,类似之前的扫描包
@import("MyConfiguration.class")  //此句没有经过测试
public class MyConfiguration {
    //注册一个bean,就相当于我们之前写的一个bean标签
    //这个方法的名字,就相当于bean标签中的id属性
    //这个方法的返回值,就相当于bean标签的calss属性
    @Bean
    public TestDao getTestDao(){
        return new TestDao();
    }
}

获取注解上下文来获取注册的bean,注意方法名是name,返回对象的类

package com.qian.service;

import com.qian.config.MyConfiguration;
import com.qian.dao.TestDao;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class ServiceTest {

    public static  void  main(String[] args){

        //如果完全使用了配置类方式去做,我们就只能通过AnnotationConfig上下文来获取容器,通过配置类的class对象加载!
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
        TestDao testDao = context.getBean("getTestDao", TestDao.class);
        System.out.println(testDao.getCat());

    }
}

七、AOP

1、Spring AOP defaults to using standard JDK dynamic proxies for AOP proxies.

默认使用JDK代理

2、使用AOP的三种方式:

2.1

首先,AOP需要pom中更新weaver包,重要 !!!如果没有调入该包,编译不报错,运行时报错!!

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.7</version>
        </dependency>

第一种:调用API接口,配合spring.xml完成功能。

java类,实现MethodBeforeAdvice,并实现before方法

package com.qian.aop;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class BeforeLog implements MethodBeforeAdvice {
    public void before(Method method, Object[] objects, Object o) throws Throwable{
        System.out.println(o.getClass().getName()+"的"+method.getName()+"方法被执行了");
    }
}

Service

package com.qian.service;

public interface UserService {
    public void add();
    public void remove();
    public void select();
    public void modify();
}

实现类

package com.qian.service.serviceimpl;

import com.qian.service.UserService;

public class UserServiceImpl implements UserService {
    public void add() {
        System.out.println("执行增加方法");
    }

    public void remove() {
        System.out.println("执行删除方法");
    }

    public void select() {
        System.out.println("执行查询方法");
    }

    public void modify() {
        System.out.println("执行更改方法");
    }
}

spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns="http://www.springframework.org/schema/beans"
       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
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

<!--    <context:component-scan base-package="com.qian">-->
<!--    </context:component-scan>-->
<!--    <context:annotation-config/>-->


    <bean id="userService" class="com.qian.service.serviceimpl.UserServiceImpl"/>
    <bean id="beforeLog" class="com.qian.aop.BeforeLog"/>
<!--    <bean id="afterLog" class="com.kaung.log.AfterLog"/>-->
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(* com.qian.service.UserService.*(..))" />
        <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>
<!--        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>-->
    </aop:config>
</beans>

测试类

package com.qian.service;

import com.qian.config.MyConfiguration;
import com.qian.dao.TestDao;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ServiceTest {

    public static  void  main(String[] args){

        //如果完全使用了配置类方式去做,我们就只能通过AnnotationConfig上下文来获取容器,通过配置类的class对象加载!
//        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
//        TestDao testDao = context.getBean("getTestDao", TestDao.class);
//        System.out.println(testDao.getCat());
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        UserService userService = (UserService)context.getBean("userService");
        userService.add();

    }
}

测试结果

spring leader选主 spring require_spring_04

第二种、自定义java类

自定义java类,作为切面方法

package com.qian.aop;

public class Diy {
    public void before(){
        System.out.println("============方法执行前===========");
    }
    public void after(){
        System.out.println("===========方法执行后============");
    }
}

spring.xml  变化较大

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns="http://www.springframework.org/schema/beans"
       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
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

<!--    <context:component-scan base-package="com.qian">-->
<!--    </context:component-scan>-->
<!--    <context:annotation-config/>-->


    <bean id="userService" class="com.qian.service.serviceimpl.UserServiceImpl"/>
    <bean id="beforeLog" class="com.qian.aop.BeforeLog"/>
<!--    第一种方式,以接口的方式-->
<!--    <bean id="afterLog" class="com.kaung.log.AfterLog"/>-->
<!--    <aop:config>-->
<!--        <aop:pointcut id="pointcut" expression="execution(* com.qian.service.UserService.*(..))" />-->
<!--        <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>-->
<!--<!–        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>–>-->
<!--    </aop:config>-->

<!--    第二种方式,以自定义类的方式-->
<!--    注入自定义类-->
    <bean name="diy" class="com.qian.aop.Diy"></bean>
 <aop:config>
<!--     自定义切面,ref要引用的类-->
     <aop:aspect ref="diy">
         <!--切入点-->
         <aop:pointcut id="point" expression="execution(* com.qian.service.serviceimpl.UserServiceImpl.*(..))"/>
         <!--具体运行方法,通知-->
         <aop:before method="before" pointcut-ref="point" />
         <aop:after method="after" pointcut-ref="point" />
     </aop:aspect>
 </aop:config>

</beans>

其余类与第一种一样

运行结果

spring leader选主 spring require_后端_05

 

第三种方案  注解AOP

spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns="http://www.springframework.org/schema/beans"
       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
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <context:component-scan base-package="com.qian">
    </context:component-scan>
<!--    <context:annotation-config/>-->

<!--    开启注解支持-->
    <aop:aspectj-autoproxy/>



    <bean id="userService" class="com.qian.service.serviceimpl.UserServiceImpl"/>
<!--    <bean id="beforeLog" class="com.qian.aop.BeforeLog"/>-->
<!--    第一种方式,以接口的方式-->
<!--    <bean id="afterLog" class="com.kaung.log.AfterLog"/>-->
<!--    <aop:config>-->
<!--        <aop:pointcut id="pointcut" expression="execution(* com.qian.service.UserService.*(..))" />-->
<!--        <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>-->
<!--<!–        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>–>-->
<!--    </aop:config>-->

<!--    第二种方式,以自定义类的方式-->
<!--    注入自定义类-->
<!--    <bean name="diy" class="com.qian.aop.Diy"></bean>-->
<!-- <aop:config>-->
<!--<!–     自定义切面,ref要引用的类–>-->
<!--     <aop:aspect ref="diy">-->
<!--         <!–切入点–>-->
<!--         <aop:pointcut id="point" expression="execution(* com.qian.service.serviceimpl.UserServiceImpl.*(..))"/>-->
<!--         <!–具体运行方法,通知–>-->
<!--         <aop:before method="before" pointcut-ref="point" />-->
<!--         <aop:after method="after" pointcut-ref="point" />-->
<!--     </aop:aspect>-->
<!-- </aop:config>-->

</beans>

注解类:

package com.qian.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class AnnotationAop {
    @Before("execution(* com.qian.service.serviceimpl.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("=========方法运行前=========");
    }
    @After("execution(* com.qian.service.serviceimpl.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("========方法运行后==========");
    }
    @Around("execution(* com.qian.service.serviceimpl.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint pj){
        System.out.println("===========环绕前============");
        try {
            Object proceed = pj.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println("============环绕后============");

    }
}

运行结果:

spring leader选主 spring require_spring leader选主_06