Spring 基础知识 超详细 初学者必看

Spring基础知识

1. IoC 与依赖注入(DI)的关系

IoC思想是把实例化对象的权力交给spring框架去做,而依赖注入则是IoC思想的具体实现
例:以前创建对象:

    public static void main(String[] args) {
        
        User user=new User();
        user.setName("FreeMan");
        user.setSex("man");
    }

现在由Spring在applicationContext.xml创建对象:

    <bean id="user" class="com.pojo.User">
        <property name="name" value="FreeMan"/>
        <property name="sex" value="Man"/>
    </bean>
        ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user =(User) app.getBean("user");
        System.out.println(user);

结果对比:
在这里插入图片描述

在这里插入图片描述
以前调用dao层方法:

public class UserServiceImp implements UserService {
    /**
     * 显示
     */
    @Override
    public void show() {
        UserDaoImp userDaoImp=   new UserDaoImp();
        userDaoImp.show();
    }
}

现在通过spring 调用dao层方法

<!--    通过配置bean 把 UserDaoImp对象放入Spring 容器里面-->
    <bean id="daoImp" class="com.dao.impl.UserDaoImp"></bean>

    <!--    通过配置bean 把 UserServiceImp对象放入Spring 容器里面-->
    <bean id="serviceImp" class="com.service.impl.UserServiceImp">
<!-- 通过属性注入 把UserDaoImp对象注入到 service 层中 -->
    <property name="userDao" ref="daoImp"/>
    </bean>
public class UserServiceImp implements UserService {
    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    /**
     * 显示
     */
    @Override
    public void show() {
   userDao.show();
    }
}
    public static void main(String[] args) {
        ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserServiceImp bean = app.getBean(UserServiceImp.class);
        bean.show();
       
    }
}

这样对比下来感觉上是 Spring 的要稍微复杂一点,但是原始的方法中 UserDaoImp 与service层耦合死了,不利于代码的修改,但spring的对象注入则是能够解决这种耦合,使之能够松耦合
得到Spring容器里面的对象并运用;
注意的是利用以上方法调用对象方法时 必须要有set方法才行
应为xml的property标签是根据属性set方法注入的

以上只是简单的了解一下spring的作用

2. applicationContext.xml基本知识

对于 Spring的配置文件里面有很深的门道,就说一下我对它的理解
首先是spring 配置的头文件,有很多命名空间 例如 context,p,mvc,aop命名空间等
如何快速配置命名空间只需要两步:

第一步

在这里插入图片描述第二步

需要加什么命名空间则直接在把刚刚复制的内容里含有beans的单词替换成自己想要的就行
例如context:

bean标签基本属性详解:bean标签把 对象放入到spring容器中
id 属性则是在Spring容器中唯一标识符,可随意写,但建议命名为类相关的名字。
class 属性:确定该类的位置。意思是告诉Spring容器,帮我实例对象的类所在位置。
property标签:设置该类的属性的是
name 则是告诉spring容器 你要设置的该类里面的那一个属性, 后面一般 value,或者ref
value属性 是给属性一般赋值
ref则是给属性 赋引用型的值一般是另一个类的实例化对象
使用构造方法进行注入
constructor-arg 标签:
name 构造方法形参名
value:赋值
ref:赋引用对象名

init-method:指定类中的初始化方法名称(前提是类方法里有方法)
destroy-method:指定类中销毁方法名称)(前提是类方法里有方法)
scope:singleton(只创建一个实例对象)无论调用多少次该对象就只有一个(在你配置好后,类加载完成就创建对象)
scope:prototype(创建多个实例对象),你调用一次该对象,他会在你调用时创建对象

如以下代码示例 ref 属性的用法:
<!--    通过配置bean 把 UserDaoImp对象放入Spring 容器里面-->
    <bean id="daoImp" class="com.dao.impl.UserDaoImp"></bean>

    <!--    通过配置bean 把 UserServiceImp对象放入Spring 容器里面-->
    <bean id="serviceImp" class="com.service.impl.UserServiceImp">
<!-- 通过属性注入 把UserDaoImp对象注入到 service 层中 -->
    <property name="userDao" ref="daoImp"/>

    </bean>
此ref=id是daoImp的实例化对象

如果属性里面有list属性则可使用
    <bean id="user" class="com.pojo.User">
        <property name="name" value="FreeMan"/>
        <property name="sex" value="Man"/>
        <property name="list">
<!--            value-type属性是填写list属性存储的值的路径-->
            <list value-type="">
<!--                可以直接 填写已经注入的id-->
                <ref bean="daoImp"/>
<!--                也可以填写需要存放对象的路径地址-->
                <bean class="com.pojo.User" id="user2">
<!--                    在里面也可以继续赋值得 引用类型的对象-->
                    <property name="sex" value="Man"/>
                </bean>
<!--                也可以填写自己想要的值-->
                <value>1</value>
            </list>
        </property>
    </bean>
属性里有map 的配置如下
        <property name="map" >
<!--      map可以设置键值对的类型 第一个value-type则是设置 值 第二行是key-type 键的类型-->
            <map value-type="" key-type="" >
                    <!--设置普通的键值对象
                     Map map=new Map()
                        map.put("a","97")
                    -->
                <entry key="" value=""/>
<!--                设置引用类型的简直对象
                        Map map=new Map()
                        map.put(Object,Object)
-->
                <entry key-ref="" value-ref=""/>
            </map>

3. IoC的新旧注解基础知识

使用注解需要在applicationContext.xml配置注解扫描:
context命名空间下的标签:  <context:component-scan>(注解扫描),
<context:property-placeholder>(加载配置文件标签)
<!--    base-package="" 需要扫描的那些包,多个包 ,可以用逗号隔开 进行多包扫面-->
    <context:component-scan base-package="com"/>
<!--    一定要加上classpath: 否则可能会报错-->
    <context:property-placeholder location="classpath:jdbc.properties"/>
Spring的原始注解理解:
原始注解有:
@Component //使用在类上用于实例化Bean(可以在该注解写上该bean id的值)@Component("")
@Controller //使用在web层类上用于实例化Bean
@Service //使用在service层类上用于实例化Bean
@Repository //使用在dao层类上用于实例化Bean
//上面四个都是直接把类实例化到Spring容器中四个都一样的有用只是分管的区域不一样,
//为了好区分该实例化层是具体的那一次就造就了这三个注解@Controller ,@Service,@Repository。

@Autowired //使用在字段上用于根据类型依赖注入(前提是该字段在spring容器中存在实例化的bean)
//如果Spring容器中有多个的同类型的实例化bean  例如 有俩个同类型的bean. id=user1, id=user2
//就必须在该字段上+@Autowired @Qualifier("user1")指定id
@Qualifier //结合@Autowired一起使用用于根据名称(bean的id)进行依赖注入

@Resource //相当于@Autowired+@Qualifier,按照名称(bean的id)进行注入
//可在字段上注入值 也可以注入spring 加载后端properties文件的值
//例如@value("${properties文件里的键名称}")
@Value //注入普通属性

@Scope //标注Bean的作用范围(之前的 singleton,prototype属性)

@PostConstruct //使用在方法上标注该方法是Bean的初始化方法
@PreDestroy //使用在方法上标注该方法是Bean的销毁化方法

新注解:

@Configuration //用于指定当前类是一个 Spring 配置类,当创建容器时会从该类上加载注解
@ComponentScan
//用于指定 Spring 在初始化容器时要扫描的包。
//作用和在 Spring 的 xml 配置文件中的context:component-scan base-package="com"/>一样
@Bean //使用在方法上,标注将该方法的返回值存储到 Spring 容器中
@PropertySource //用于加载.properties 文件中的配置
@Import //用于导入其他配置类
properties文件内容
jdbc.user=root

主配置类

@Configuration//声明配置类
@ComponentScan("com")//告诉Spring 需要扫那些包,多个包可用逗号隔开
@Import(SprringConfig_1.class)//导入其它配置类
public class SpringConfig {
@Bean//该bean的默认id是 方法名;
public User getUser(){
    User user=new User();
    user.setName("FreeMan");
    return  user;
}

}

另一个配置类

@Configuration//配置类
@PropertySource("classpath:jdbc.properties")//加载properties文件
public class SprringConfig_1 {
@Value("${jdbc.user}")//把properties文件赋值给该字段
    private String name;
    @Bean("user")//在添加一个bean为user的对象到容器中
    public User userTest(){
        User user=new User();
        user.setName(name);
        return user;
    }
}

测试name属性为FreeMan,以及name属性为root
的User对象是否注入到Spring框架

public class SpringUserTest {

    public static void main(String[] args) {
//        注解加载配置类
        AnnotationConfigApplicationContext app =
         new AnnotationConfigApplicationContext(SpringConfig.class);
        //测试两个配置文件里的user对象是否注入并能否取出
        User bean = (User) app.getBean("user");

        User bean1 = (User) app.getBean("getUser");
        System.out.println("我是注解Bean为默认值方式注入的  "+bean.getName());
        System.out.println("我是注解Bean为(user)方式注入的  "+bean1.getName());

    }
}

结果如下:

在这里插入图片描述
上面内容就是SpringIoC 需要记住的基本知识

4.Spring测试

需要导入Spring与junit集合的测试依赖

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.0.5.RELEASE</version>
    </dependency>

我直接在我的测试类上修成Spring -test集成的代码

//或者@RunWith(SpringJUnit4ClassRunner.class)
@RunWith(SpringRunner.class)

//加载是Spring配置类
@ContextConfiguration(classes = SpringConfig.class)
/*加载Spring配置文件
     注意加载文件 与加载配置类的区别
     配置类不是字符串型,直接括号里面写配置类的字节码文件但要加前缀 classes=配置了类名.class
     文件是字符串型 字符串前面还需要带上classpath:
     @ContextConfiguration("classpath:applicationContext.xml")
    */
public class SpringUserTest {
//    因为这里有两个同类型的bean 我就使用Resource进行注入
    //也可以是使用
//    @Autowired
  //  @Qualifier("user")

@Resource(name = "user")
private User user;

    @Autowired
    @Qualifier("getUser")
    private User getUSer;//注入另外一个bean
@Test//在方法上直接定义一个Test注解可直接运行方法
    public void testBean(){
    System.out.println("注解@Bean('user')的bean的值====>"+user.getName());
    System.out.println("注解@Bean()的bean的值====>"+getUSer.getName());

}
}

结果如下
在这里插入图片描述

5. AOP切面

首先需要导入依赖

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>5.0.5.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.8.13</version>
    </dependency>

①什么是aop
面向切面编程,不修改源代码对方法增强,减少代码重复,两种动态代理技术
jdk动态代理基于接口代理
cglib动态代理基于父类代理
需要掌握的术语点
连接点:方法(可理解为所有的方法都是连接点)
切入点:需要增强的方法(可理解为:即将要将该方法增强)
通知/增强:检查到目标方法将要执行时,执行的方法(可理解为,我在切入点周围加入的另一个方法,这个方法作用是切入点方法的增强)
切面:通知/增强+切入点
②aop 的xml配置

<!--    把目标bean注入到Spring容器中-->
    <bean id="targetImp" class="com.aop.TargetImp"/>

<!--   把通知类/增强类 注入spring容器-->
    <bean id="aspectConfig" class="com.aop.AspectConfig"/>

<!--    开始把通知类增强类进行配置-->
    <aop:config>
<!-- 告诉spring 我的通知类是什么-->
        <aop:aspect ref="aspectConfig">
<!--告诉spring我的要增强的方法的具体位置
expression="execution()"切面表达式-->
            <aop:pointcut id="point" expression="execution(* com.aop.Target.*(..))"/>
<!--aspectConfig 类里面的方法 adviceMethod()监听到切点表达式里的方法执行时,
告诉spring容器 我的 adviceMethod()方法在哪里执行-->
            <aop:after method="adviceMethod" pointcut-ref="point"/>
        </aop:aspect    
<!--以a方法作为(通知)方法
aop:after method="a" 监测的方法之后(无论是否异常)都执行方法a -->
<!-- <aop:around method="a"监测的方法之前以及之后执行a方法-->
<!-- <aop:after-throwing method="a"监测的方法异常后执行该方法-->
<!-- <aop:before method="a"监测的方法之前执行a方法-->
<!-- <aop:after-returning method="a"监测的方法之后执行a方法-->
    </aop:config>

我xml的配置是把切点表达式给抽取出来了,也可以在 配置增强方法 加上单独的切点表达式
如下:

  <aop:after-returning method="adviceMethod" pointcut="execution(* com.aop.*.*(..))"/>

aop的xml配置需要注意事项:
切点表达式的使用
切点表达式尤其重要:
*号代表的是任意 包名前的* 代表的是任意返回值 (注意返回值的这个*号与包名要有空格) ..代表的是当前包下及其子包下的所有 包名后的.*代表当前包下的所有类 ,类名后的 .*代表当前类下的所有方法 , 方法后的(..)代表是任意参数
举例:

  1. * com.dao.imp.*UserDaoImp.*(..):表示 任意返回值 com包下的dao包下的imp包下的UserDaoImp类下的任意方法的任意参数
  2. * com.dao.imp.*.*(..) 任意返回值 com包下的dao包下的imp包下的任意类下的任意方法的任意参数
  3. * com.dao .. *.*(..) 任意返回值 com包下的dao当前包及其子包的任意类下的任意方法的任意参数
  4. 切点表达试还有很多。就不列举了

aop的配置结构
<aop:config
<aop:pointcut id=“” expression=“execution()”
<aop:aspect
<aop:before //<aop :after(等增强方法的具体执行位置)
</aop:config

6. SpringAOP注解

aop需要使用到的注解
通知类

@Aspect//告诉Spring这是aop通知类

@Component//注入bean
public class AspectConfigs {
    //抽取切点表达式
//    在一个空方法上加上@Pointcut注解写上表达式
    @Pointcut("execution(* com.aop.anno.*.*(..))")
    public void pointExpression() {
    }

    //前置增强方法
    @Before("pointExpression()")
    public void before() {
        System.out.println("前置的增强");
    }

    //    环绕增强方法
    @Around("pointExpression()")
//    环绕增强需要使用ProceedingJoinPoint接口定义环绕前与环绕后的逻辑
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕前增强");
        Object proceed = joinPoint.proceed();
        System.out.println("环绕后增强");
        return proceed;
    }
}

需要增强的方法类(目标对象类)

@Component
public class TargetAnno {
    public void show() {
        System.out.println("该方法要增强......");
    }
}

Spring配置类

@Configuration//配置类
@ComponentScan("com.aop.anno")//扫包
@EnableAspectJAutoProxy//开启自动代理,spring才会进行方法的增强
public class SpringAopAnnoConfig {
}

@Component(在类上写)前面提到就不说了
@Acpset:(在通知类名上写)告诉spring这是我的增强类
@Pointcut:(在空方法上写,应为注解必须要有依赖,不能单独存在),抽取切点表达式
@Before,@Round,@After(在通知类里的方法上写)告诉Spring增强方法的类型
@EnableAspectJAutoProxy(在类上写),告诉Spring 开启自动代理

最后总结一看所有用到的注解
希望看到这些注解都知道是什么意思

Ioc常用注解

@Component
@Controller
@Service
@Repository
@Autowired
@Qualifier
@Resources
@Value
@Scope
@PostConstruct
@PreDestory
@Configuration
@Bean
@ComponentScan
@PropertySource
@Import

测试常用注解

@Runwith
@ContextConfiguration

Aop常用注解

@Aspect
@EnableAspectjAutoProxy
@Ponitcut
@Before
@After
@AfterThrowing
@AfterReturning
@Around

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值