Spring学习笔记

目录

1. 作用域,name,id区别,生成对象模式,生成对象时间

2.Spring给对象赋值的4种方式

3.复杂数据类型注入

4.实例化对象的几种方法

4.1四种方式

4.2静态工厂

5.传统方式和Spring创建对象对比

6.注解开发

6.1xml文件配置

6.2各种注解

6.3 man.properties

6.4 测试代码

7. 代理模式

7.1基础代理理解

7.2JDK动态代理

7.3Cjlib动态代理

8.  SpringAOP中5种通知类型

8.1xml配置

8.2注解配置

9. Spring-Mybatis和Spring事务

9.1步骤及事务的xml配置

9.2mapper及mybatis-config.xml

9.3 事务的注解配置

1. 作用域,name,id区别,生成对象模式,生成对象时间

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

    <!--
    4大作用域对象:page,request(请求范围),session(回话范围),application(应用范围)

    Spring框架创建对象,一个bean就是一个对象
    创建对象一定要使用new关键字吗?错 反射也可以创建对象 newInstance()
    创建对象一定要调用构造方法吗? 对-->

    <!--Spring框架可以管理对象的生命周期,IOC容器管理对象
    bean标签中id和name的区别
    id属性:表示对象的唯一标识,整合SpringIOC容器中,ID不能重复,不能以数字开头(合法标识符)
    name属性:表示对象的名字,一个对象可以有多个名字

    SpringIOC中,生成的对象是单例的SingleTon scope="singleton" 默认的!
    多例 scope="prototype" 每次从Spring框架中获取的对象是新new出来的对象
    scope="request" web环境,表示每次请求,Spring框架会新new一个对象
    scope="session" web环境,表示会话范围内,Spring框架会新new一个对象
    scope="globalsession" web环境,表示全局会话范围内,Spring框架会新new一个对象
    -->
    <bean id="m1" class="com.weng.bean.Man">
        <!--赋值,底层掉的set方法-->
        <property name="age" value="90"/>
        <property name="address" value="wuqiao"/>
        <property name="name" value="zhouxingxing"/>
        <property name="car" ref="c1"/>
    </bean>
    <bean id="c1" class="com.weng.bean.Car">
        <property name="name" value="falali"/>
    </bean>
    <bean id="c2" class="com.weng.bean.Car">
        <property name="name" value="baoshijie"/>
    </bean>

    <!--多例 scope="prototype"
    lazy-init:懒初始化,表示Spring创建对象的时机
    前提:scope="singleton"
    Spring中对象默认是,框架一旦加载启动,那么立即创建容器中所有的对象lazy-init="default"或者false
    lazy-init="true"表示Spring框架在启动加载的时候没有立即创建对象,而是在使用的时候创建指定对象,节省内存
    如果scope="prototype"那么不管lazy-init,都是使用时创建

    init-method初始化方法
    destory-method销毁对象方法
    -->
    <bean id="p" class="com.weng.bean.Person" scope="prototype" lazy-init="true"
          init-method="init" destroy-method="destory">
        <property name="name" value="刘德华"/>
    </bean>
</beans>

2.Spring给对象赋值的4种方式

<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--Spring给对象赋值的几种方式(对象属性注入方法)-->

    <!--方法1:set注入:调用set方法属性赋值,默认调用set方法-->
    <bean id="d1" class="com.weng.bean.Dog">
        <property name="id" value="1"/>
        <property name="name" value="wudi"/>
    </bean>

    <!--方法2:构造注入:调用构造方法赋值-->
    <bean id="d2" class="com.weng.bean.Dog">
        <constructor-arg index="0" value="2"/>
        <constructor-arg index="1" value="wahd"/>
    </bean>

    <!--方式3:p命令空间赋值,语法简洁,本质是set注入-->
    <bean id="d3" class="com.weng.bean.Dog" p:id="3" p:name="小狗"/>

    <!--方式4:SpEl表达式注入-->
    <bean id="s4" class="com.weng.bean.Dog">
        <property name="id" value="4"/>
        <!--引用别的对象的值,d3.name引用d3的name值-->
        <property name="name" value="#{d3.name}"/>
    </bean>

</beans>

3.复杂数据类型注入

 <!--Spring复杂的数据类型注入-->
    <bean id="m" class="com.weng.bean.ManTwo">
        <!--数组-->
        <property name="hobby">
            <list>
                <value>无敌1</value>
                <value>无敌2</value>
                <value>无敌3</value>
            </list>
        </property>
        <!--set-->
        <property name="books">
            <set>
                <value>红楼梦</value>
                <value>西游记</value>
                <value>水浒传</value>
                <value>三国演义</value>
            </set>
        </property>
        <!--list-->
        <property name="phones">
            <list>
                <value>华为p40</value>
                <value>华为p30</value>
                <value>华为p20</value>
                <value>华为p10</value>
            </list>
        </property>
        <property name="map">
            <map>
                <entry key="川">
                    <value>四川</value>
                </entry>
                <entry key="鄂">
                    <value>湖北</value>
                </entry>
            </map>
        </property>
        <property name="properties">
            <props>
                <prop key="url">http://127.0.0.1:3306/studentdb</prop>
                <prop key="username">root</prop>
            </props>
        </property>
    </bean>
</beans>

4.实例化对象的几种方法

4.1四种方式

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

    <!--Spring 实例化对象的几种方法-->

    <!--方法1:调用无参构造方法-->
    <bean id="s1" class="com.weng.bean.Student">
        <property name="id" value="1"/>
        <property name="name" value="wudi2"/>
    </bean>

    <!--方法2:调用有参数的构造方法
    type可省略
    -->
    <bean id="s2" class="com.weng.bean.Student">
        <constructor-arg index="0" type="int" value="222"/>
        <constructor-arg index="1" type="java.lang.String" value="wudi"/>
    </bean>

    <!--方式3:静态工厂-->
    <bean id="s3" class="com.weng.bean.StudentFactory" factory-method="getStudent2">
        <constructor-arg value="小王"></constructor-arg>

    </bean>

    <!--方式4:非静态工厂,方法非静态的
    要先创建个工厂对象
    -->
    <bean id="studentFactory" class="com.weng.bean.StudentFactory"/>
    <bean id="s4" factory-bean="studentFactory" factory-method="getStudent">
        <constructor-arg value="5"></constructor-arg>
    </bean>


4.2静态工厂

//静态工厂
public class StudentFactory {
    static Map<String,Student> map = new HashMap<String, Student>();

    static {
        map.put("小周",new Student(1,"haha"));
        map.put("小刘",new Student(2,"haha"));
        map.put("小王",new Student(3,"haha"));
        map.put("小李",new Student(4,"haha"));
    }
    //静态工厂要加static,非静态工厂不需要
    public Student getStudent(String name){
        return map.get(name);
    }
    public static Student getStudent2(String name){
        return map.get(name);
    }
}

5.传统方式和Spring创建对象对比

public class TestSpring {
    //传统方式创建对象
    @Test
    public void test1(){
        Man man = new Man();
        man.setName("周星星");
        man.setAge(18);
        man.setAddress("吴桥");
    }

    //使用Spring创建对象
    @Test
    public void test2() throws InterruptedException {
        //1.启动Spring框架,并加载配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //2.从Spring框架容器中获取一个对象
        Man m1 = context.getBean("m1", Man.class);
        System.out.println(m1);
        m1.setName("wudi");
        Man m2 = context.getBean("m1",Man.class);
        //比较地址,地址中保存的值变了
        System.out.println(m1==m2);
        System.out.println("person中各个方法");
        Person p = context.getBean("p",Person.class);
        Thread.sleep(3000);
        p.setName("wuwu");
        context.close();
    }
}

6.注解开发

6.1xml文件配置

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

    <!--Spring注解开发,扫描包下的所有类,然后使用反射类上的注解,给带注解的类进行实例化-->
    <context:component-scan base-package="com.weng.*"/>
    <!--加载外部的配置文件-->
    <context:property-placeholder location="classpath:man.properties" file-encoding="UTF-8"/>
</beans>

6.2各种注解


@Data
@NoArgsConstructor
@AllArgsConstructor
@Component("m1")
@Scope("singleton")
/*@Component:给一个SpringIOC容器中的类生成对象,相当在xml中写了一个bean标签
默认的对象名字是类名首字母小写如:man
@Value(注入值)给属性注入值
@Autowired:自动装配,根据类型在SpringIOC容器中去匹配一个对象,如果容器中有多个类型匹配的对象,那么就会异常
数组等可以匹配多个
@Qualifier和@Autowired一起用,如果@Autowired类型匹配到了多个对象,那么使用@Qualifier人工指定具体指向哪个对象
@Resource默认是根据类型匹配IOC容器中的对象,类似@Autowired,如果匹配到多个异常
但@Resource还可以执行名字去匹配对象,@Resource还支持配置文件的写法
@Scope("singleton")单例模式property多例模式
@PostConstruct初始化方法@PreDestroy对象销毁方法
web三层:本质和@component一样
@Controller("对象名")控制创建对象,默认首字母小写
@Service,@Repository业务逻辑层和Dao层
*/
public class Man {
    @Value("${man.id}")
    private Integer id;
    @Value("${man.name}")
    private String name;
    @Value("${man.sex}")
    private String sex;

    //ref类似用法,引用对象
    //@Autowired
    //@Qualifier("chineseGirl")
    @Resource(name="${man.girl}")
    private Igirl igirl;
    //@Autowired
    //private Igirl[] igirl2;
    @PostConstruct
    public void init(){
        System.out.println("对象初始化方法");
    }
    @PreDestroy
    public void destory(){
        System.out.println("对象销毁方法");
    }
}

6.3 man.properties

man.id=9527
man.name=周星驰
man.sex=男
man.girl=englishGirl

6.4 测试代码

//使用Spring-test和junit整合测试,简化开发,注解测试
@RunWith(SpringJUnit4ClassRunner.class)//使用注解的方式启动Spring框架
@ContextConfiguration("classpath:applicationContext-man.xml")//执行Spring配置文件
public class testSpring {
    @Autowired
    Man man;

    @Test
    public void test1(){
        System.out.println(man.getId().toString());;
    }
}

7. 代理模式

7.1基础代理理解

目标类

//目标类
@Service
public class UserServiceImpl implements UserService {

    public int addUser(User user) {
        System.out.println("模拟新增user到数据库"+user);

        return 0;
    }

    public int delUser(int id) {

        System.out.println("模拟从数据库删除user,删除的id为"+id);

        return 0;
    }
}

代理类代理目标类

//代理类
public class UserServiceProxy implements UserService {
    Transaction tx = new Transaction();
    UserService userService = new UserServiceImpl();//目标对象
    public int addUser(User user) {
        tx.openTx();
        userService.addUser(user);
        tx.commit();
        return 0;
    }

    public int delUser(int id) {
        tx.openTx();
        userService.delUser(id);
        tx.commit();
        return 0;
    }
}

7.2JDK动态代理

import com.weng.tx.Transaction;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
//实现InvocationHandler接口 反射

public class ObjectIntercepter implements InvocationHandler {
    Object target;//目标对象
    public ObjectIntercepter(Object target){
        this.target = target;
    }
    Transaction tx=new Transaction();//事务方法

    //执行拦截的方法,拦截目标类中的目标方法
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        tx.openTx();
        //调用目标对象的目标方法,反射调用方法
        Object result  = method.invoke(target,args);
        tx.commit();
        return result;
    }
}
/业务逻辑层代码
public class testProxy {
    UserService us=new UserServiceProxy();
    @Test
    public void test1(){
        //真实对象
        UserService target = new UserServiceImpl();
        ObjectIntercepter intercepter=new ObjectIntercepter(target);
        //生成一个代理类对象,此处的us不是正式的userServiceImpl对象,是代理类对象
        //只能用UserService接口接收,因为不是实现类
        UserService us = (UserService) Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),intercepter);
        int i = us.addUser(new User(1, "wuw"));
        System.out.println(i);
        int i2 = us.delUser(1);
        System.out.println(i2);
    }
}

7.3Cjlib动态代理

import com.weng.tx.Transaction;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CjlibIntercepter implements MethodInterceptor {
    Transaction tx = new Transaction();

    //o代理对象,method子类,args参数数组,methodProxy父类
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        tx.openTx();
        methodProxy.invokeSuper(o,args);
        tx.commit();
        return null;
    }
}
//业务逻辑层代码
public class testCjlib  {
    UserService us=new UserServiceProxy();
    @Test
    public void test1(){
        CjlibIntercepter h = new CjlibIntercepter();

        Enhancer enhancer = new Enhancer();
        //设置拦截器
        enhancer.setCallback(h);
        //设置要生成的子类的父类是谁
        enhancer.setSuperclass(UserServiceImpl.class);
        //生成子类 父类=子类
        UserServiceImpl us=(UserServiceImpl)enhancer.create();
        int i = us.addUser(new User(1, "wuw"));
        System.out.println(i);
        int i2 = us.delUser(1);
        System.out.println(i2);
    }
}

8.  SpringAOP中5种通知类型

8.1xml配置


    <!--Spring AOP(底层就是代理设计模式) XML配置-->
    <!--目标target对象-->
    <bean id="userServiceImpl" class="com.weng.service.impl.UserServiceImpl"/>

    <!--增强类(advice 通知类) 事务类对象-->
    <bean id="tx" class="com.weng.tx.Transaction"/>

    <!--配置AOP-->
    <aop:config>
        <!--切入点:那些类的那些方法需要被植入增强代码
        类中所有方法:
        execution(* com.weng.service.impl.UserServiceImpl.*(..))-->
        <aop:pointcut id="pointcut" expression="execution(public int com.weng.service.impl.UserServiceImpl
        .addUser(com.weng.bean.User))"/>
        <!--配置增强-->
        <aop:aspect ref="tx">
            <!--前置增强-->
            <aop:before method="openTx" pointcut-ref="pointcut"/>
            <!--返回增强-->
            <aop:after-returning method="commit" pointcut-ref="pointcut"/>
            <!--异常通知-->
            <aop:after-throwing method="rollbackTx" pointcut-ref="pointcut" throwing="ex"/>
            <!--最终通知-->
            <aop:after method="finnalyMethod" pointcut-ref="pointcut"/>
            <!--环绕通知-->
            <aop:around method="arroundMethod" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>

</beans>

8.2注解配置

@Component
@Aspect
public class Transaction {
    //切入点表达式抽取出去公用起来
    @Pointcut("execution(* com.weng.service.impl.*.*(..))")
    public void pointcut(){

    }
    //*后面要有个空格
    @Before("Transaction.pointcut()")
    public void openTx(){
        System.out.println("开启事务");
    }
    @AfterReturning("execution(* com.weng.service.impl.*.*(..))")
    public void commit(){
        System.out.println("提交事务");
    }
    //异常要把throwing = "ex"写上
    @AfterThrowing(value = "execution(* com.weng.service.impl.*.*(..))",throwing = "ex")
    public void rollbackTx(Exception ex){
        System.out.println("异常通知"+ex.getMessage());
    }
    @After("execution(* com.weng.service.impl.*.*(..))")
    public void finnalyMethod(){
        System.out.println("最终通知,释放资源等");
    }
    //环绕通知 joinPoint连接点是个专业术语,其实就是目标对象的封装对象
    @Around("execution(* com.weng.service.impl.*.*(..))")
    public Object arroundMethod(ProceedingJoinPoint joinPoint){
        //调用真实的目标方法
        Object result = null;
        try {
            System.out.println("环绕通知---前置");
            result = joinPoint.proceed();
            System.out.println("环绕通知---后置");
        } catch (Throwable throwable) {
            System.out.println("环绕通知---异常");
            throwable.printStackTrace();
        }finally {
            System.out.println("环绕通知---最终");
        }
        return result;
    }
}

9. Spring-Mybatis和Spring事务

9.1步骤及事务的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"
       xmlns:tx="http://www.springframework.org/schema/cache" xmlns:aop="http://www.springframework.org/schema/aop"
       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 http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--Spring和Mybatis整合的配置-->
    <!--1,扫描包-->
    <context:component-scan base-package="com.weng.*"/>

    <!--2,加载外部配置文件-->
    <context:property-placeholder location="classpath:jdbc.properties" file-encoding="utf-8"/>
    <!--3,配置德鲁伊数据库连接池数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <!--4,配置MyBatis的SqlSessionFactory:作用给MyBatis生成sqlsession-->
    <bean class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--设置session工厂使用的连接池,这里是上面配置的德鲁伊数据库连接池-->
        <property name="dataSource" ref="dataSource"/>
        <!--设置mapper文件的位置-->
        <property name="mapperLocations" value="mappers/*.xml"/>
        <!--设置MyBatis的配置文件位置-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <!--设置MyBatis实体类别名-->
        <property name="typeAliasesPackage" value="com.weng.bean"/>
    </bean>
    <!--5,指定Mapper接口的位置,Spring底层会给Mapper层通过代理生成对象-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--Spring框架会自动通过动态代理模式(反射)生成对象-->
        <property name="basePackage" value="com.weng.mapper"/>
    </bean>
    <!--6,配置MyBatis的平台事务管理器,管理项目中的事务-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--
    7,配置事务增强
    <tx:advice id="advice">
        <tx:attributes>
            timeout="-1" 默认值是-1 表示默认不超时,一旦事务方法执行超过指定时间,自动回滚
            read-only="false"默认值,一般的查询方法设置为只读(数据库底层会根据只读属性,进行适当的优化)
            isolation="DEFAULT"当前会话的隔离级别,默认是default(数据库的默认级别)
            rollback-for=""配置什么样的异常需要回滚默认值是rollback-for="java.lang.Exception"只要出异常就回滚
            norollback-for则相反
            propagation="REQUIRED"事务的传播特性,默认是REQUIRED
            REQUIED当前没事务就新建个事务,当前有事务就按当前事务,被ty_catch包裹的异常会触发回滚
            REQUIED_NEW不管当前有没有事务都用新的事务
            NEVER不能有事务,有就报异常
            NESTED被ty_catch包裹的异常不会触发回滚

            <tx:method name="addMoney" timeout="4000"/>
        </tx:attributes>
    </tx:advice>
    8,配置事务切面
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(* com.weng.service.impl.*.*(..))"/>
        <aop:advisor advice-ref="advice" pointcut-ref="pointcut"/>
    </aop:config>
    -->



    <!--7,8换成注解配置支持-->
    <tx:annotation-driven transaction-manager="transactionManager"/>

</beans>

9.2mapper及mybatis-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--上述的话必须放在所有xml文件中的第一行,且不能有空格-->
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--接口和xml文件的名字要保持一致
namespace要是接口的全路径-->
<mapper namespace="com.weng.mapper.UserMapper">
    <select id="findUsers" resultType="com.weng.bean.User">
        select * from t_user
    </select>
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>

    <settings>
        <!--MyBatis日志输出-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
</configuration>

9.3 事务的注解配置

@Service
@Transactional(readOnly = true)//查询配置只读事务,效率更高  方法的优先级大于类
public class UserServiceImpl implements UserService {
    @Autowired
    UserMapper userMapper;
    //事务注解见xml7,8
    //外面类写只读,类里面需要不是只读的事务设置为false
    @Transactional(timeout = -1,readOnly = false, isolation = Isolation.DEFAULT,
            noRollbackFor = {Exception.class,ArithmeticException.class},propagation = Propagation.REQUIRED)
    public List<User> findUsers() {
        return userMapper.findUsers();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值