Day61_Springday02

(1)Spring回顾

①Spring是什么?

Spring是一个轻量级DI/IOC与AOP的容器框架

  • DI(依赖注入)
  • IOC(控制反转)
  • AOP(面向切面)

面试题:BeanFactory与ApplicationContext的区别?
答:ApplicationContext是BeanFactory的子类,它拥有更加强大的一些方法(邮件,国际化,…),BeanFactory创建的Bean默认是懒加载,ApplicationContext是迫切加载!!!

②导包(Spring)

  • ApplicationContext.xml配置文件中配置
    配置Spring需要的包
    ①Spring的核心包 spring-core
    ②Context包 spring-context
    ③aop的包 spring-aop
    ④切面的一个包(织入) aspectjweaver
    ⑤Spring的测试包 spring-test
    ⑥junit的测试支持 junit
<!--Spring的核心包-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>4.2.5.RELEASE</version>
</dependency>
<!--Context包-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.2.5.RELEASE</version>
</dependency>
<!--aop的包-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>4.2.5.RELEASE</version>
</dependency>
<!--切面的一个包(织入)-->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.8</version>
</dependency>

<!-- Spring的测试包 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>4.2.5.RELEASE</version>
    <!--scope:范围,只能在test包中使用-->
    <scope>test</scope>
</dependency>
<!--junit的测试支持-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

③引入一些插件与资源

  • 需要读到java中的xml文件(默认不会编译)
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
    </plugins>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.xml</include>
            </includes>
        </resource>
        <resource>
            <directory>src/test/java</directory>
            <includes>
                <include>**/*.xml</include>
            </includes>
        </resource>
    </resources>
</build>

(2)构造器注入

通过constructor-arg标签注入

  • index:索引
  • name:属性名
  • type:属性类型
  • 默认不写:按照顺序注入
  • value:普通值
  • ref:引用类型(外部引用)

例:

①index:索引

<bean id="myBean" class="com.luo._02_constructor.MyBean">
	<constructor-arg index="0" value="小王八"/>
    <constructor-arg index="1" value="18"/>
</bean>

②name:属性名

<bean id="myBean" class="com.luo._02_constructor.MyBean">
	<constructor-arg name="name" value="小王八羔子"/>
    <constructor-arg name="age" value="8"/>
</bean>

③type:属性类型

<bean id="myBean" class="com.luo._02_constructor.MyBean">
	<constructor-arg type="java.lang.String" value="老乌龟"/>
	<constructor-arg type="java.lang.Integer" value="88"/>
</bean>

④默认不写:按照顺序注入

<bean id="myBean" class="com.luo._02_constructor.MyBean">
	<constructor-arg value="老乌龟"/>
	<constructor-arg value="88"/>
</bean>

引用类型:外部与内部引用两种方式
⑤ref:外部引用

<bean id="youBean" class="com.luo._02_constructor.YouBean"></bean>

<bean id="myBean" class="com.luo._02_constructor.MyBean">
	<constructor-arg value="aaa"/>
    <constructor-arg value="66"/>
    <!--外部引入-->
    <!--<constructor-arg ref="youBean"/>-->
    <constructor-arg>
	    <!--内部引入-->
	    <bean class="com.luo._02_constructor.YouBean"></bean>
    </constructor-arg>
</bean>

⑥内部引用

<bean id="myBean" class="com.luo._02_constructor.MyBean">
	<constructor-arg>
	    <!--内部引入-->
	    <bean class="com.luo._02_constructor.YouBean"></bean>
	</constructor-arg>
</bean>

(3)属性注入

①普通属性注入

<bean id="myBean" class="com.luo._03_di.MyBean">
	<property name="id" value="2"/>
	<property name="name" value="古二娃"/>
	<property name="sex" value="true"/>
	<property name="salary" value="8000"/>
</bean>

②List/Set/Map注入

普通属性注入

List<String> list;
Set<String> set;
Map<Integer,String> map;
<bean id="myBean" class="com.luo._03_di.MyBean">
	<property name="list">
		<!--有序可重复-->
	    <list>
	        <value>孤儿</value>
	        <value>秀儿</value>
	        <value>低能儿</value>
	        <value>低能儿</value>
	    </list>
	</property>
	<property name="set">
	    <!--无需不可重复-->
	    <set>
	        <value>悟空</value>
	        <value>八戒</value>
	        <value>老沙</value>
	        <value>老沙</value>
	    </set>
	</property>
	
	<property name="map">
        <map>
            <entry key="1" value="aaa"/>
            <entry key="2" value="bbb"/>
            <entry key="3" value="ccc"/>
        </map>
    </property>
</bean>

引用类型注入

List<OtherBean> otherBeanList;
Set<OtherBean> otherBeanSet;
Map<Integer,OtherBean> otherBeanMap;
<bean id="myBean" class="com.luo._03_di.MyBean">
	<!--List<OtherBean> otherBeanList;-->
	<property name="otherBeanList">
	    <list>
	        <!--内部引入-->
	        <bean class="com.luo._03_di.OtherBean"/>
	        <bean class="com.luo._03_di.OtherBean"/>
	        <!--外部引入-->
	        <ref bean="otherBean"/>
	        <ref bean="otherBean"/>
	    </list>
	</property>
	<!--Set<OtherBean> otherBeanSet;-->
	<property name="otherBeanSet">
	    <set>
	        <!--内部引入-->
	        <bean class="com.luo._03_di.OtherBean"/>
	        <bean class="com.luo._03_di.OtherBean"/>
	        <!--外部引入-->
	        <ref bean="otherBean"/>
	        <ref bean="otherBean"/>
	    </set>
	</property>
	<!--Map<Integer,OtherBean> otherBeanMap;-->
	<property name="otherBeanMap">
	    <map>
	        <entry key="1" value-ref="otherBean"/>
	        <entry key="2" value-ref="otherBean"/>
	        <entry key="3" value-ref="otherBean"/>
	    </map>
	</property>
</bean>

③数组注入

private String[] arrays;
<bean id="myBean" class="com.luo._03_di.MyBean">
	<!--String[] arrays;-->
	<!--<property name="arrays">
	    <array>
	        <value>一</value>
	        <value>二</value>
	        <value>三</value>
	    </array>
	</property>-->
	<!--简写格式-->
	<property name="arrays" value="四,五,六"/>
</bean>

④Properties注入

private Properties props1;
private Properties props2;
<bean id="myBean" class="com.luo._03_di.MyBean">	
	<!--Properties props1;-->
	<property name="props1">
	    <props>
	        <prop key="kkk">KKKKK中国</prop>
	        <prop key="aaa">AAAAA</prop>
	        <prop key="bbb">BBBBB</prop>
	    </props>
	</property>
	<!--简写格式(不支持中文)-->
	<property name="props2">
	    <value>
	        <!--可以空格和=号分隔-->
	       <!-- kkk KKKKK中国
	        aaa AAAAA
	        bbb BBBBB-->
	        kkk=KKKKK中国
	        aaa=AAAAA
	        bbb=BBBBB
	    </value>
	</property>
</bean>

(4)XML的自动注入(了解即可,不用管)

  • 自动注入有两种方式 (通过类型与通过名称)
  • 设置全局的自动注入 <beans … default-autowire=“byType/byName”>
  • 单独为某一个bean配置自动注入 <bean … autowire=“byType/byName”>

(5)全注解(重要)

①全注解配置及使用

xml配置context
扫描相应的包

<context:component-scan base-package="com.luo._04_anno"/>

具体配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
    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
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
">
    <!--扫描包-->
    <context:component-scan base-package="com.luo._04_anno"/>
</beans>

在相应的类上加注解

  • @Controller:控制层
  • @Service:业务层
  • @Repository:持久层
  • @Component:组件(一个bean不知道在哪一层用这个)
  • @Autowired:注入功能

②如果出现多个bean类型一样怎么办?

  • 注解的bean有默认名称(类名【首字母小写】) 如 userDaoImpl
  • 先通过类型注入,再通过名称注入
  • 修改bean的名称 Component/Service/Repository/Controller(“名称”)
  • 在注入bean的时候加上一个限定注解 (通过注解确定名称)
@Autowired
@Qualifier("userJPADaoImpl")
//@Resource(name = "userJDBCDao")
private IUserDao userDao;

(6)代理模式(了解即可)

概念图:
在这里插入图片描述

  • 代理模式分为静态代理动态代理
  • 静态代理和装饰者有些相似,但是没什么用
  • Spring使用的是动态代理,有两种方式,由Spring自行选择
    ①JDK方式(有接口的时候用)
    ②没有接口的是CGLIB

动态代理

格式:

Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
        new Class[] { Foo.class },
        handler);
  • newProxyInstance:创建代理对象
  • 参数1:ClassLoader loader :类加载器(随便给它一个)
  • 参数2:Class<?>[] interfaces:接口(为什么这里是一个数组)
  • 参数3:InvocationHandler:处理器,为了增强功能(自己实现)
//准备一个真实主题颜色对象
IUserService userService = new UserServiceImpl();

IUserService proxy = (IUserService)Proxy.newProxyInstance(userService.getClass().getClassLoader(),
        userService.getClass().getInterfaces(),
        new InvocationHandler() {
            //实现的代码
            /*
             * Object proxy:代理对象(不用它)
             * Method method:执行方法
             * Object[] args:方法参数
             * */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                TxManager txManager = new TxManager();
                Object result = null;
                try {
                    txManager.begin();
                    //在这里面完成功能增强
                	//通过反射执行相应的方法
                    result = method.invoke(userService, args);
                    txManager.commit();
                } catch (Exception e) {
                    txManager.rollback();
                    e.printStackTrace();
                }  finally {
                    txManager.close();
                }
                return result;
            }
        }
);
proxy.delete();

(7)Spring的AOP

XML版本

aop配置
三要素:何时,何地,做什么

①引入aop的头

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

②配置真实主题角色

<bean id="userService" class="com.luo._07_aopxml.service.impl.UserServiceImpl"></bean>

③配置事务管理对象,用于增强

<bean id="txManager" class="com.luo._07_aopxml.TxManager"></bean>

④配置三要素(何时,何地,做什么)

何地:该包的I开头Service结尾的接口的所有方法切面

<aop:pointcut id="pointcut" expression="execution(* com.luo._07_aopxml.service.I*Service.*(..))"/>

何时:

  • aop:before 前置通知
  • aop:after-returning 后置通知
  • aop:after-throwing 异常通知
  • aop:after 最终通知
  • aop:around 环绕通知(可取代以上所有)
  • aop:aspect->切面(切点与增强)
  • ref=“txManager”:引入增强的类
<aop:config>
        <aop:pointcut id="pointcut" expression="execution(* com.luo._07_aopxml.service.I*Service.*(..))"/>
        <aop:aspect ref="txManager">
            <!--前置通知-->
            <!--<aop:before method="begin" pointcut-ref="pointcut"/>-->
            <!--后置通知-->
            <!--<aop:after-returning method="commit" pointcut-ref="pointcut"/>-->
            <!--异常通知-->
            <!--<aop:after-throwing method="rollback" pointcut-ref="pointcut" throwing="e"/>-->
            <!--后置通知-->
            <!--<aop:after method="close" pointcut-ref="pointcut"/>-->
            <!--环绕通知 可以取代上面所有通知-->
            <aop:around method="around" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>

⑤若使用环绕通知

若使用环绕测试,如果有环绕通知,其它通知就不需要了,并且
需要在事务对象中定义around(ProceedingJoinPoint joinPoint)方法

  • ProceedingJoinPoint joinPoint Spring会为你传一个连接点对象
  • joinPoint.proceed();//执行方法
public class TxManager {
    public void begin(){
        System.out.println("开启事务...");
    }
    public void commit(){
        System.out.println("提交事务...");
    }
    public void rollback(Throwable e){
        System.out.println("回滚事务...原因是:"+e.getMessage());
    }
    public void close(){
        System.out.println("关闭事务...");
    }
    //连接点 Spring会为你传一个连接点对象
    public void around(ProceedingJoinPoint joinPoint){
        //System.out.println(joinPoint.getArgs());//方法参数
        //System.out.println(joinPoint.getSignature());//方法签名(包含方法的所有信息)
        //System.out.println(joinPoint.getTarget());//真实对象
        //System.out.println(joinPoint.getThis());//代理对象
        try {
            begin();
            joinPoint.proceed();//执行方法
            commit();
        } catch (Throwable e) {
            rollback(e);
            e.printStackTrace();
        } finally {
            close();
        }

    }
}

⑥xml全部代码

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

<!--配置真实主题角色-->
    <bean id="userService" class="com.luo._07_aopxml.service.impl.UserServiceImpl"></bean>
    <!--配置事务管理对象,用于增强-->
    <bean id="txManager" class="com.luo._07_aopxml.TxManager"></bean>
    <!--
        aop配置
        三要素:何时,何地,做什么
        切点id:随便取
        表达式 expression(何地):execution(* com.luo._07_aopxml.service.I*Service.*(..))
                          定义到I*Service的所有方法
        aop:aspect->切面(切点与增强)
        ref="txManager":引入增强的类
         aop:before:前置通知
            aop:after-returning:后置通知
            aop:after-throwing:异常通知(异常抛出去才能使用)与Throwable e的e相同
            aop:after:最终通知
             try {
                    aop:before:前置通知
                    //通过反射执行方法
                    result = method.invoke(userService, args);
                    aop:after-returning:后置通知
                } catch (Exception e) {
                    aop:after-throwing
                    e.printStackTrace();
                }  finally {
                    aop:after:最终通知
                }
            aop:around:环绕通知(可以取代上面的所有通知)
    -->
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(* com.luo._07_aopxml.service.I*Service.*(..))"/>
        <aop:aspect ref="txManager">
            <!--&lt;!&ndash;前置通知&ndash;&gt;
            <aop:before method="begin" pointcut-ref="pointcut"/>
            &lt;!&ndash;后置通知&ndash;&gt;
            <aop:after-returning method="commit" pointcut-ref="pointcut"/>
            &lt;!&ndash;异常通知&ndash;&gt;
            <aop:after-throwing method="rollback" pointcut-ref="pointcut" throwing="e"/>
            &lt;!&ndash;后置通知&ndash;&gt;
            <aop:after method="close" pointcut-ref="pointcut"/>-->
            <!--环绕通知 可以取代上面所有通知-->
            <aop:around method="around" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>

</beans>

⑦测试方式

  • 查看一下这个对象是否已经被代理
  • 声明必需是接口
  • 测试一下有异常与没有异常的区别

全注解版本

需要在相应的bean上加注解控制层/业务层/持久层/普通组件…

  • ①引入aop和context的头
  • ②开启扫描包
  • ③开启支持aop注解
  • ④其他配置都在T下Manager(事物类中)

xml配置①②③

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       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
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
">
       <!--开启扫描包-->
        <context:component-scan base-package="com.luo._08_aopanno"/>
       <!--支持aop注解-->
       <aop:aspectj-autoproxy/>
</beans>

TxManager类配置④

  • 注意:切点的名字是方法名()
@Component
@Aspect  //<aop:aspect ref="txManager">
public class TxManager {
    /*
    * 配置一个切点(随便定义一个方法,方法名随意取)
    * <aop:pointcut id="pointcut" expression="execution(* com.luo._07_aopxml.service.I*Service.*(..))"/>
    * */
    @Pointcut("execution(* com.luo._08_aopanno.service.I*Service.*(..))")
    public void pointcut(){}

    //前置通知  <aop:before method="begin" pointcut-ref="pointcut"/>
    //@Before("pointcut()")//注意用的是方法名加()  pointcut()
    public void begin(){
        System.out.println("开启事务...");
    }

    //@AfterReturning("pointcut()")
    public void commit(){
        System.out.println("提交事务...");
    }

    //@AfterThrowing(value = "pointcut()",throwing = "e")
    public void rollback(Throwable e){
        System.out.println("回滚事务...原因是:"+e.getMessage());
    }

    //@After("pointcut()")
    public void close(){
        System.out.println("关闭事务...");
    }

    @Around("pointcut()")//环绕通知
    public void around(ProceedingJoinPoint joinPoint){
        try {
            begin();
            joinPoint.proceed();
            commit();
        } catch (Throwable e) {
            rollback(e);
            e.printStackTrace();
        } finally {
            close();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值