spring

HelloSpring

Hello 对象是谁创建的?
hello对象是由Spring创建的
Hello 对象的属性是怎么设置的?
hello对象的属性是由Spring容器设置的

IOC本质

IOC是一种思想,而依赖注入(DI)只是它的一种实现。

Spring过程:Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从IOC容器中取出需要的对象。XML配置Bean时,Bean的定义信息和实现是分离的,而是采用注解的方式将两者合为一体,最新版的Spring已经可以零配置实现IOC,主要是因为Bean的定义信息以注解的形式定义在实现类中。

控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式,Spring中实现控制反转的是IOC容器,其实现方法是依赖注入(DI)。

使用spring来创建对象

    <bean id="hello" class="Hello">
        <property name="str"  value="Spring"> </property>
    </bean>

2.IOC创建对象

1.使用无参构造,创建对象 默认

   public Usert() {
        System.out.println("usert被创建了");
    }
    
    
    xml
     <bean id="usert" class="com.pojo.Usert">
        <property name="name" value="xfn">

        </property>

2.使用有参构造创建对象

1.类型赋值

在前面的场景中,容器 可以 使用简单类型的类型匹配 使用显式指定构造函数参数的类型 type属性。 例如:

<bean  id = "exampleBean"  class = "examples.ExampleBean" > 
<constructor-arg  type = "int"  value = "7500000" /> 
<constructor-arg  type = "java.lang.String"  value = "42" / > 
</bean> 
下标赋值

使用 index明确指定的属性 构造函数参数的索引。 例如:

<bean  id = "exampleBean"  class = "examples.ExampleBean" > 
<constructor-arg  index = "0"  value = "7500000" /> 
<constructor-arg  index = "1"  value = "42" /> 
</bean > 
构造函数参数名称

从 Spring 3.0 开始,您还可以使用构造函数参数 值消歧的名称:

<bean  id = "exampleBean"  class = "examples.ExampleBean" > 
<constructor-arg  name = "years"  value = "7500000" /> 
<constructor-arg  name = "ultimateanswer"  value = "42" /> 
</bean > 

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

3.Spring配置

3.1 别名

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iiTspmOx-1658999117399)(C:\Users\21886\AppData\Roaming\Typora\typora-user-images\image-20220224104414308.png)]

3.2 beans的配置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QTUYZDEJ-1658999117400)(spring.assets/image-20220224105218027.png)]

3.3import导入

4.DI依赖注入

4.1构造器注入

4.2 set方式注入

依赖注入: Set注入!
。依赖: bean对象的创建依赖于容器
I
。注入: bean对象中的所有属性,由容器来注入!|

bean | ref | idref | list | set | map | props | value | null

4.3其他方式注入

带有 p 命名空间的 XML 快捷方式
带有 c 命名空间的 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:p="http://www.springframework.org/schema/p"
       xmlns:c= "http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="user" class="com.pojo.User" p:name="陈平安" p:age="18">
    </bean>
    <bean id="user2" class="com.pojo.User" c:name="徐凤年" c:age="17"/>
</beans>

5.bean作用域

ScopeDescription
singleton(Default) Scopes a single bean definition to a single object instance per Spring IoC container.
prototypeScopes a single bean definition to any number of object instances.
requestScopes a single bean definition to the lifecycle of a single HTTP request; that is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext.
sessionScopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext.
global sessionScopes a single bean definition to the lifecycle of a global HTTP Session. Typically only valid when used in a portlet context. Only valid in the context of a web-aware Spring ApplicationContext.

5.1单例模式(spring默认机制)

   <bean id="user" class="com.pojo.User" p:name="陈平安" p:age="18" scope="singleton"/>

5.2 原型模式:每次从容器中get的时候,都会产生一个新对象(多线程)

<bean  id = "accountService"  class = "com.foo.DefaultAccountService"  scope = "prototype" /> 

request,session,global,session只在web开发中使用

6.bean的自动装配

byName:自动在容器上下文中查找。和自己对象set方法后面的值对应的beanid!
<bean id="cat" class="com.pojo.Cat"></bean>
    <bean id="dog" class="com.pojo.Dog"></bean>
    <bean id="people" class="com.pojo.People" autowire="byName">
        <property name="name" value="陈平安"></property>
        
    </bean>
byType:自动在容器上下文中查找,和自己对象属性类型相同的bean!
<bean  class="com.pojo.Cat"></bean>
    <bean class="com.pojo.Dog"></bean>
    <bean id="people" class="com.pojo.People" autowire="byType">
        <property name="name" value="陈平安"></property>

    </bean>
总结

byname的时候,需要保证所有bean的id唯一,并且这 个bean需要和自动注入的属性的set方法的值一致!
bytype的时候,需要保证所有bean的class唯一 , 并且这个bean需要和自动注入的属性的类型-致!

7.使用注解实现自动装配

开启注解

 <context:annotation-config/> 
@Autowired

直接在属性上使用即可!也可以在set方式上使用!
使用Autowired我们可以不用编写Set方法了,前提是你这个自动装配的属性在I0C (Spring) 容器中存在,且符
合名字byname!

@Autowired源码

public @interface Autowired {
    boolean required() default true;
}
//如果显示定义了Autowired的required属性为false,说明这个对象可以为nu11, 否则不允许为空
  @Autowired( required = false)
  private  Cat cat;

如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解@Autowired]完成的时候、我们可以
使用@Qualifier(value=“xx”)去配置@Autowired的使用,指定一个唯一的bean对象注入!

pub1ic class People {
@Autowired
@qualifier(va1ue="cat111")
private Cat cat;
@Autowired
@qualifier(value=" dog222")
private Dog dog;
private string name;
}

@Resource

自动装配通过名字。类型

@Resource
  private  Cat cat;
//    @Autowired
//    @Qualifier(value = "dog22")
 @Resource(name = "dog23")
  private Dog dog;
@Component

代表组件

@Component
public class User {
    @Value("fengnian")
    public  String name ;
    @Value("xufengnian")
    public void setName(String name) {
        this.name = name;
    }
}

@Component有几个衍生注解,我们在web开发中,会按照mvc三层架构分层!
。dao [@Repository]
。service [@Service ]
。controller , @Controller]
这四个注解功能都是一样的, 都是代表将某个类注册到Spring中,装配Bean

作用域

@Component
@Scope
public class User {
    @Value("fengnian")
    public  String name ;
    相当于<property name="name" value="xufengnian"
    @Value("xufengnian")
    public void setName(String name) {
        this.name = name;
    }
}

总结

xml与注解:
。xml更加万能,适用于任何场合!维护简单方便
。注解不是自己类使用不了,维护相对复杂!
xml与注解最佳实践:
。xml用来管理bean;
。注解只负责完成属性的注入;
。必须让注解生效,就需要开启注解的支持

<!--指定 要扫描的包,这个包下的注解就会生效-->
<context:component-scan base-package="com"/>
    <context:annotation-config/>

8.使用Javaconfig实现配置

@Configuration

代表这是配置类,和beans.xml一样

@Configuration
public class config2 {
}
@ComponentScan

扫描包,引入配置类的地址

@ComponentScan("com.pojo")
@bean

//注册一个bean ,就相当 之前写的个bean标签
//这个方法的名字,就相当fbean标签中的id属性
//这个方法的返回值,就相当J bean标签中的class属性

@Configuration
@ComponentScan("com.pojo")
@Import(config2.class)
public class config {

    @Bean
    public  User getUser(){
        return  new User();//就是返回要注入到bean的对象
    }
}

注意!如果完全使用了配置类方式去做,我们就只能通过AnnotationConfig 上下 文来获取容器,通过配置类的class对象加载
public class test {
    public static void main(String[] args) {
        如果完全使用了配置类方式去做,我们就只能通过AnnotationConfig 上下 文来获取容器,通过配置类的class对象加载!
       ApplicationContext context = new AnnotationConfigApplicationContext(config.class);
        User getUser = (User) context.getBean("getUser");
        System.out.println(getUser.getName());

    }
}

@Import 引入配置类的class对象

@Configuration
@ComponentScan("com.pojo")
@Import(config2.class)
public class config {

    @Bean
    public  User getUser(){
        return  new User();
    }
}

9.代理模式

角色分析:

●抽象角色: -般会使用接口或者抽象类来解决
●真实角色:被代理的角色
●代理角色:代理真实角色,代理真实角色后,我们一般会做一-些附属操作
●客户:访问代理对象的人! .

静态代理

代码步骤: .

1.接口

package com.zsr.demo01;
//租房
public interface Rent {
    public  void rent();


}
2.真实角色
package com.zsr.demo01;

public class Host implements Rent {
    public  void  rent(){
        System.out.println("房东要出租房子");
    }
}
3.代理角色
package com.zsr.demo01;

public class Proxy {
    private  Host host;

    public Proxy() {
    }

    public Proxy(Host host) {
        this.host = host;
    }

    public  void rent(){
host.rent();
setHost();
hetong();
fare();
    }
    //看房
    public void setHost(){
        System.out.println("中介带你开房");
    }


    //中介收费
    public void hetong(){
        System.out.println("签订合同");
    }
    //中介收费
    public void fare(){
        System.out.println("中介收费");
    }
}
4.客户端访问代理角色
package com.zsr.demo01;

public class Clinet {
    public static void main(String[] args) {
        //调用 房东要租房子
        Host host = new Host();
        //中介帮房东租房子,但是呢?代理角一一般会有-些附属操作!
        Proxy proxy = new Proxy();
        //你不用面对房东,直接找中介租房即可!
        proxy.rent();
    }
}

代理模式的好处:

●可以使真实角色的操作更加纯粹!不用去关注一些公共的业务
●公共也就就交给代理角色!实现了业务的分工!
●公共业务发生扩展的时候,方便集中管理!
缺点:
●一个真实角色就会产生一个代理角色;代码量会翻倍,开发效率降低

AOP实现机制

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iKsywaO9-1658999117409)(spring.assets/image-20220225205647381.png)]

动态代理

动态代理的本质 反射机制实现

●动态代理分为两大类:基于接口的动态代理, 基于类的动态代理
。基于接口— JDK动态代理[我们在这里使用]
。基于类: cglib
。java字节码实现 : javasist

Proxy 代理,
InvocationHandler调用处理程序

代码

public class ProxyInvocationHandler implements InvocationHandler {

  /*  Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
            new Class<?>[] { Foo.class },
            handler);
*/
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    //生成得到代理类
    public  Object getProxy(){
        return   Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this);

    }
    //处理代理实例,并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //动态代理的本质 反射机制实现
        log(method.getName());
        Object result = method.invoke(target, args);

        return result;

    }
    
    public  void log( String msg){
        System.out.println("生成了" + msg + "方法");
    }
public class Client {
    public static void main(String[] args) {
        //真实代理
        serviceImpi service = new serviceImpi();
        //代理角色 不存在
        ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
        //设置要代理的对象
       proxyInvocationHandler.setTarget(service);
       //动态生成代理类
        service proxy =(service) proxyInvocationHandler.getProxy();
        proxy.add();
        proxy.delete();
        proxy.query();
        proxy.update();

    }

10.AOP

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CN0LLR6J-1658999117410)(spring.assets/image-20220226095807979.png)]

实现Spring实现AOP

导入maven依赖

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

方式一使用原生的Spring API接口
<!--注册bean-->
<bean id="Service" class="com.service.impi.impi"/>
    <bean id="log" class="com.service.log"/>
    <bean id="afterlog" class="com.service.Afterlog"/>
    <!--方式一使用原生的Spring API接口-->
<!--配置aop需要导入aop的约束-->
    <aop:config>
       <!--切入点:expression 表达式 execution(要执行的位置 修饰符 返回值 类名 方法名 参数)    (..)代表任意参数-->
        <aop:pointcut id="pointcut" expression="execution(* com.service.impi.impi.*(..))"/>

        <!--执行环绕增加-->
       <!-- 把log这个类切入到   <aop:pointcut id="printcut" expression="execution(* com.service.impi.*(..))"/>这个方法上面-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterlog" pointcut-ref="pointcut"/>

    </aop:config>

方式二使用自定义类(切面定义)
<!--方式二 自定义类-->
<bean id="diy" class="com.diy.DiyPointcut"/>
<aop:config>
  <!--  自定义切面 ref要引用的类-->
    <aop:aspect ref="diy">
       <!-- 切入点-->
        <aop:pointcut id="point" expression="execution(* com.service.impi.impi.*(..))"/>
        <!--通知-->
        <aop:before method="before" pointcut-ref="point"/>
        <aop:after method="after" pointcut-ref="point"/>
    </aop:aspect>
</aop:config>



package com.diy;

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


package com.service.impi;

import com.service.Service;

public class impi  implements Service {
    @Override
    public void add() {
        System.out.println("新增用户");
    }

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

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

    @Override
    public void query() {
        System.out.println("查询用户");
    }
}

方式三注解开发
@Aspect

标志这个类是一个切面

@Before 执行前
@After执行后
@Around环绕增强

在环绕增强中,我们可以给定一一个参数, 代表我们要获取处理切入的点;

@Aspect
public class AnnotationPointCut {
    @Before("execution(* com.service.impi.impi .*(..))")
    public  void before(){
        System.out.println("方法执行前");
    }

@After("execution(* com.service.impi.impi .*(..))")
    public  void after(){
        System.out.println("方法执行后");
    }

    @Around("execution(* com.service.impi.impi .*(..))")
    public  void around(ProceedingJoinPoint joinPoint) throws  Throwable{
        System.out.println("环绕前");
        Signature signature = joinPoint.getSignature();//获得签名
        System.out.println(signature);
        Object proceed = joinPoint.proceed();
        System.out.println("环绕后");

    }

11.Mybatis整合

1.导入相关jar包
。junit
。mybatis
。mysq
。spring相关的
。aop织入
。mybatis-spring

<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>
  <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>2.0.7</version>
    </dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.16</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.3.16</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.8</version>
</dependency>

步骤

1.编写数据源配置

  1. sqlSessionFactory

  2. sqlSessionTemplate

  3. User实体类

  4. UserMapper接口

  5. UserMapper.xml

<mapper namespace="com.mapper.UserMapper">
    <select id="selectUser" resultType="com.pojo.User">
        select * from mybatis.user
    </select>

spring-dao.xml

 <!--DataSource:使Spring的数据源替换Mybatis的配置c3pθ dbcp druid
我们这里使用Spring提供的JDBC : org. springframework. jdbc. datasource
-->
 <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
     <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
     <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
     <property name="username" value="root"/>
     <property name="password" value="123456"/>
 </bean>
<!--sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <!--绑定mybatis配置文件-->

        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:com/mapper/*.xml"/>
    </bean>
<!--SqlSessionTemplate就是常用的sqlSession-->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
    <!--只能使用构造器注入sqlSessionFactory,因为它没有set方法-->

    <constructor-arg ref="sqlSessionFactory" index="0"/>
</bean>



<!--开启注解支持 jdk(expose-proxy="false") cglib (expose-proxy="true")-->
    <aop:aspectj-autoproxy expose-proxy="true"/>
</beans>

4.需要给接口加实现类[]

UserMapperImpi

public class UserMapperImpi implements  UserMapper {
    private SqlSessionTemplate sqlSession;

    public void setSqlSession(SqlSessionTemplate sqlSession) {
        this.sqlSession = sqlSession;
    }

    @Override
    public List<User> selectUser() {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
      return mapper.selectUser();

    }
}

5.将自己写的实现类,注入到Spring中,

applicationcontext.xml

<import resource="spring-dao.xml"/>
    <!---->
    <bean id="userMapper" class="com.mapper.UserMapperImpi">
        <property name="sqlSession" ref="sqlSession"/>
    </bean>

6.测试使用即可

2.第二种继承SqlSessionDaoSupport

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hOEWuLmb-1658999117413)(spring.assets/image-20220305192536465.png)]

public class UserMapperImpi2  extends SqlSessionDaoSupport implements  UserMapper{
    @Override
    public List<User> selectUser() {
       /* SqlSession sqlSession = getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        return mapper.selectUser();*/
        return getSqlSession().getMapper(UserMapper.class).selectUser();
    }
}

applicationcontext.xml

<!---->
<bean id="userMapper2" class="com.mapper.UserMapperImpi2">
   <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

12.声明式事务

什么是事务

事务ACID原则:
●原子性
●一致性
●隔离性
。多个业务可能操作同-个资源,防止数据损坏
●持久性
。事务一旦提交,无论系统发生什么问题,结果都不会再被影响,被持久化的写到存储器中!

2.spring中的事务管理

●声明式事务: AOP
●编程式事务:需要再代码中,进行事务的管理

事务

<!--配置声明式事务-->


    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--结合AOP实现事务的织入-->
    <!--配置事务的类-->

<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <!--给那些方法配置事务-->
        <!--配置事务的传播特性: I new propagation=-->

                <tx:method name="add" propagation="REQUIRED"/>
                <tx:method name="delete"  propagation="REQUIRED"/>
                <tx:method name="update"  propagation="REQUIRED"/>
                <tx:method name="query" read-only="true"/>
                <tx:method name="*"  propagation="REQUIRED"/>
            </tx:attributes>
        </tx:advice>

    <!--配置事务切入-->
    <aop:config>
        <!--当前事务的所有类所有方法-->
        <aop:pointcut id="txPointCut" expression="execution(* com.mapper.*.*(..))"/>
    </aop:config>
<!--配置声明式事务-->


    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--结合AOP实现事务的织入-->
    <!--配置事务的类-->

<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <!--给那些方法配置事务-->
        <!--配置事务的传播特性: I new propagation=-->

                <tx:method name="add" propagation="REQUIRED"/>
                <tx:method name="delete"  propagation="REQUIRED"/>
                <tx:method name="update"  propagation="REQUIRED"/>
                <tx:method name="query" read-only="true"/>
                <tx:method name="*"  propagation="REQUIRED"/>
            </tx:attributes>
        </tx:advice>

    <!--配置事务切入-->
    <aop:config>
        <!--当前事务的所有类所有方法-->
        <aop:pointcut id="txPointCut" expression="execution(* com.mapper.*.*(..))"/>
    </aop:config>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值