Java小白学习指南【day49】---Spring进阶

一、依赖注入

首先在idea创建普通的Maven项目,在pom.xml中进行导包

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.itsource</groupId>
    <artifactId>day57_spring</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>4.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.2.5.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.8</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

    <build>
        <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>

</project>

1、构造参数的注入(注意要提供有参构造)

创建一个实体类

public class Mybean {
    private Long id;
    private String name;
    ......
}

在SpringTest-Context.xml(测试时候方便,使用了@ContextConfiguration不写路径,会默认扫描同包下的:类名-Context.xml)

	<bean id="Mybean" class="cn.itsource._01di.domain.Mybean">
        <!--使用类型进行注入-->
        <constructor-arg type="java.lang.Long" value="22" />
        <constructor-arg type="java.lang.String" value="22"/>
    </bean>

	<bean id="Mybean" class="cn.itsource._01di.domain.Mybean">
        <!--使用下标进行注入,从0开始,推荐使用这种-->
        <constructor-arg index="0" value="66" />
        <constructor-arg index="1" value="二狗"/>
    </bean>

	<!-- 按照名称注入,名称必须一致 -->
    <bean id="MyBean" class="cn.itsource._01di.domain.Mybean">
        <constructor-arg name="id" value="1" />
        <constructor-arg name="name" value="张三娃" />
    </bean>

2、外部bean与内部bean注入

在domain加入引用类型

	/*引用属性*/
    private YouBean youBean;

外部bean注入

	<!--外部定义-->
    <bean id="YouBean" class="cn.itsource._01di.domain.YouBean" />
    <bean id="Mybean" class="cn.itsource._01di.domain.Mybean">
        <constructor-arg index="0" value="666" />
        <constructor-arg index="1" value="二狗"/>
        <constructor-arg index="2" ref="YouBean"/><!--注意这里使用的是外部的id-->
    </bean>

内部bean注入

	<bean id="Mybean" class="cn.itsource._01di.domain.Mybean">
        <constructor-arg index="0" value="666" />
        <constructor-arg index="1" value="二狗"/>
        <constructor-arg ><!--内部bean注入-->
            <bean class="cn.itsource._01di.domain.YouBean" />
        </constructor-arg>
    </bean>

3、普通属性的注入

创建一个实体类

public class TestBean {
    // 简单属性
    private Boolean sex;
    private BigDecimal salary;
    // 对象属性
    private List<String> list;
    private Set<String> set;
    private List<OtherBean> otherBeanList;
    private Set<OtherBean> otherBeanSet;
    private String[] arrays;
    //下面这个是重点
    private Properties props1;
    .......
}
<!--普通属性的注入-->
    <bean id="TestBean" class="cn.itsource._01di.domain.TestBean">
        <property name="sex" value="true"/>
        <property name="salary" value="6666"/>
        <property name="list" >
            <list>
                <value>nihao</value>
                <value>666</value>
                <value>嘿嘿嘿</value>
            </list>
        </property>
    </bean>

4、其他属性的注入

 	<!--其他属性的注入-->
    <bean id="otherBean" class="cn.itsource._01di.domain.OtherBean"/>
    <bean id="testBean" class="cn.itsource._01di.domain.TestBean">
        <property name="otherBeanSet">
            <set><!--set不可重复-->
                <!--内部bean,会创建多个-->
                <bean class="cn.itsource._01di.domain.OtherBean" />
                <bean class="cn.itsource._01di.domain.OtherBean" />
                <!--外部bean只有一个-->
                <ref bean="otherBean" />
                <ref bean="otherBean" />
            </set>
        </property>
    </bean>

数组的注入

	<bean id="testBean" class="cn.itsource._01di.domain.TestBean">
        <!--完整版-->
        <property name="arrays">
            <array>
                <value>xxx</value>
                <value>yyy</value>
                <value>zzz</value>
            </array>
        </property>
        <!--简写-->
	<property name="arrays" value="A,B,C" />
    </bean>

5、Properties的注入

	<!--Properties的注入-->
    <bean id="testBean" class="cn.itsource._01di.domain.TestBean">
        <property name="props1">
            <props>
                <prop key="driver">org.Jpa.dialect.HSQLDialect</prop>
                <prop key="url">com.mysql.jdbc.Driver </prop>
            </props>
        </property>
    </bean>

二、Spring的AOP

1、AOP的概述

AOP即Aspect Oriented Program,面向切面编程,是面向对象编程(OOP)的一种增强模式,可以将项目中与业务无关的,却为业务模块所共同调用的非核心代码封装成(比如事务管理、日志管理、权限控制等等)一个个切面,然后在运行的时候通过动态代理的方式织入到核心业务功能中。

2、Spring实现AOP的方式

要想实现AOP的配置,要满足三点,配置的三要素:

  • 何时:在哪里执行,在代码之前、之后
  • 何地:在哪个方法执行
  • 做什么:要完成什么样的功能扩展

3、XML实现AOP(代理模式)

①、添加aop命名空间

SpringTest-Context.xml

xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd

②、创建service与service实现类

DepartmentServiceImpl

public class DepartmentServiceImpl implements IDeprtmentService {
    @Override
    public void save() {
        System.out.println("DepartmentServiceImpl  save.....");
    }
    @Override
    public void delete() {
        System.out.println("DepartmentServiceImpl  delete.....");
    }
}

UserServiceImpl

public class UserServiceImpl implements IUserService {
    @Override
    public void save() {
        System.out.println("UserServiceImpl  save.....");
        /*int i=1/0; 测试回滚使用*/
    }

    @Override
    public void delete() {
        System.out.println("UserServiceImpl  delete.....");
    }
}

③、准备事物对象

public class TxManager {
    //开启方法
    public void begin(){
        System.out.println("开启事务....");
    }
    //提交方法
    public void commit(){
        System.out.println("提交事务....");
    }
    //回滚方法
    public void rollback(){
        System.out.println("回滚事务....");
    }
    //关闭方法
    public void close(){
        System.out.println("关闭事务....");
    }
    //环绕方法
    public void around(ProceedingJoinPoint joinPoint){//环绕时需要执行service中的方法
        try {
            begin();
            joinPoint.proceed();
            commit();
        } catch (Throwable e) {//环绕时执行service中的方法需要将异常抛掷最大
            e.printStackTrace();
            rollback();
        } finally {
            close();
        }
    }
}

④、AOP配置

<!--创建bean-->
    <bean id="userServiceImpl" class="cn.itsource._02aopXml.service.impl.UserServiceImpl"/>
    <bean id="departServicImpl" class="cn.itsource._02aopXml.service.impl.DepartmentServiceImpl"/>
    <!--第一步:创建事物管理器-->
    <bean id="TxManage" class="cn.itsource._02aopXml.TxManager"/>
    <!--第二部:AOP配置-->
    <aop:config>
        <!--配置三要素,配置切点,expression:找到切点的方法-->
        <aop:pointcut id="pointcut" expression="execution(* cn.itsource._02aopXml.service.I*Service.*(..))"/>
        <!--第三步:配置切面-->
        <aop:aspect ref="TxManage">
            <!--配置前置通知-->
            <!--<aop:before method="begin" pointcut-ref="pointcut"/>-->
            <!--配置后置通知-->
            <!--<aop:after-returning method="commit" pointcut-ref="pointcut"/>-->
            <!--配置异常通知-->
            <!--<aop:after-throwing method="rollback" pointcut-ref="pointcut"/>-->
            <!--配置最终通知-->
            <!--<aop:after method="close" pointcut-ref="pointcut"/>-->

            <!--配置环绕通知-->
            <aop:around method="around" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>

上述注释的部分,使用了环绕通知后,就不需要上述四个通知!

⑤、功能测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration//不写路径,会默认扫描同包下的:类名-Context.xml
public class SpringTest {
    @Autowired
    private IUserService userService;
    @Autowired
    private IDepartmentService departmentService;
    @Test
    public void testSpringTest(){
        userService.save();
        userService.delete();
        departmentService.save();
        departmentService.delete();
    }
}

4、注解实现AOP

①、配置文件

需要在SpringTest-Context.xml进行配置AOP与Context

 	xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"

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

	<!--开启spring的扫描-->
    <context:component-scan base-package="cn.itsource._03aopanno"></context:component-scan>
    <!--开启aop注解扫描-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

②、创建事务管理器

在注解方式中,对事物管理器需要使用@Component与@Aspect尤其是后面的,同时还是按照三要素进行配置,依旧需要切面、切点。

@Component//声明为一个spring的bean
@Aspect//AOP的类注解-----><aop:aspect ref="TxManage">配置切面
public class TxManager {
    //声明切点
    @Pointcut("execution(* cn.itsource._03aopanno.service.I*Service.*(..))")
    public void txPoint(){}

    @Before("txPoint()")
    public void begin(){
        System.out.println("开启事务....");
    }

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

    @AfterThrowing(value = "txPoint()",throwing = "e")//这里要将异常参数配置一致
    public void rollback(Throwable e){
        System.out.println(e.getMessage());
        System.out.println("回滚事务....");
    }

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

一般不使用上述这种配置方式,而使用环绕通知

@Component//声明为一个spring的bean
@Aspect//AOP的类注解-----><aop:aspect ref="TxManage">配置切面
public class TxManager {
    //声明切点
    @Pointcut("execution(* cn.itsource._03aopanno.service.I*Service.*(..))")
    public void txPoint(){}

    public void begin(){
        System.out.println("开启事务....");
    }

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

    public void rollback(Throwable e){
        System.out.println(e.getMessage());
        System.out.println("回滚事务....");
    }

    public void close(){
        System.out.println("关闭事务....");
    }
    //环绕方法
    @Around("txPoint()")
    public void around(ProceedingJoinPoint joinPoint){//环绕时需要执行service中的方法
        try {
            begin();
            joinPoint.proceed();
            commit();
        } catch (Throwable e) {//环绕时执行service中的方法需要将异常抛掷最大
            e.printStackTrace();
            rollback(e);
        } finally {
            close();
        }
    }
}

这里的@Component, 这个注解和@Component、@Controller和我们最常见的@Service注解是一个作用,都可以将一个类声明为一个Spring的Bean。它们的区别到不在于具体的语义上,更多的是在于注解的定位上。

  • @Repository注解,对应的是持久层即Dao层(Mapper层),其作用是直接和数据库交互,通常来说一个方法对应一条具体的Sql语句

  • @Service注解,对应的是服务层即Service层,直接调用Dao层的某个方法了

  • @Controller注解,对应的是控制层即MVC设计模式中的控制层,其作用是接收用户请求,根据请求调用不同的Service取数据,并根据需求对数据进行组合、包装返回给前端

  • @Component注解,这个更多对应的是一个组件的概念,如果一个Bean不知道属于拿个层,可以使用@Component注解标注

1606908960771

③、使用XML配置方法中的service与service实现类,进行测试

三、代理模式

是一种编程的思想(方式),帮我们实现一个外层的封装,除了能够实现我们想要的业务,还能做功能的扩展。

1、静态代理

基本不用

2、动态代理

①、JDK

代理的类有接口,用在被接口修饰的类上(例如service)

②、CGLIB

代理的类没有接口就使用这个(直接使用实现类)

这里springAOP使用的就是动态代理的模式,底层自动帮我们实现动态代理;如果有接口就使用JDK方式,如果没有就使用CGLIB。

简单的来说上面的注解方式我们就在使用代理模式

1606918226451

这里如果我们在test中注入的是实现类,呢么程序运行后会报错bean创建错误

因为我们使用AOP将UserServiceImpl代理了,所有不能注入实现类了,是通过<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

四、创建Bean的方式

1、实例化公共的无参构造方式

最常用的

<bean id="testBean" class="cn.itsource._01di.domain.TestBean" />

2、使用FactoryBean

spring在集成其他框架的时候,其他框架一般情况下不会直接提供创建对象的方式,在spring中就需要通过FactoryBean的方式来解决创建bean的问题。

<!--使用FactoryBean,spring在看到FactoryBean后,会自动找到其中的方法getObject(),得到返回值的类,并且管理起来-->
    <bean id="car" class="cn.itsource._04bean.CarFactoryBean" />

创建FactoryBean实体类

/*泛型:表明当前类是用来操作car类的*/
public class CarFactoryBean implements FactoryBean<Car>{
    /*创建需要的类对象*/
    @Override
    public Car getObject() throws Exception {
        return new Car();
    }
    /*确定返回值类型*/
    @Override
    public Class<?> getObjectType() {
        return Car.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}

3、工厂类方式----静态方法

创建实体类car,再创建一个CarFactory

public class CarFactory {
    public static Car creatCar(){
        return new Car();
    }
}

在配置SpringTest-Context.xml

	<!--静态方法-->
    <bean id="car" class="cn.itsource._04bean.CarFactory" factory-method="creatCar"/>

4、工厂类方式----动态方法

CarFactory需要将static去掉,变为动态

<!--动态方法-->
    <bean id="carFactory" class="cn.itsource._04bean.CarFactory"/>
    <bean id="car" factory-bean="carFactory" factory-method="creatCar"/>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值