Spring基础学习

Spring学习

Spring简介

Spring四个方面的功能:

  1. Ioc/DI
  2. AOP
  3. 事务
  4. JdbcTemplate

Spring:解决企业级应用开发的复杂性而创造的。服务端的开发,测试性,松耦合

Spring下载

maven

Ioc

Ioc概念

控制反转,对一个对象的控制权的反转

将对象的创建、初始化、销毁交给容器管理,Bean注册到Spring容器中,使用时。其他对象需要使用Bean是,直接去Spring容器中要

进行bean注入,使用反射方法创建对象

Bean的获取

xml中定义bean

ClassPathXmlApplicationContext
FileSystemXmlApplicationContext

属性注入

构造方法注入

<bean class="org.javagirl.ioc.model.User" id="user">
<!--    查找构造方法-->
    <constructor-arg value="1" name="id"/>
    <constructor-arg value="2" name="username"/>
    <constructor-arg value="3" name="address"/>
</bean>

set方法注入


<bean class="org.javagirl.ioc.model.User" id="user2">
    <property name="id" value="2"></property>
    <property name="username" value="2"></property>
    <property name="address" value="2"></property>
</bean>

p名称空间注入

<bean class="org.javagirl.ioc.model.User" id="user3" p:username="javagirl" p:id="3" p:address="java.com">

</bean>

工厂方法容器注入

静态工厂注入

实例工厂注入:获取两个实例,更加具体

复杂属性注入

对象注入
<bean class="org.javagirl.ioc.model.User" id="user4">
    <property name="id" value="2"></property>
    <property name="username" value="2"></property>
    <property name="address" value="2"></property>
    <property name="cat" ref="cat"></property>
</bean>
<bean id="cat" class="org.javagirl.ioc.model.Cat">
    <property name="name" value="xiaoxiao">
    </property>
    <property name="age" value="4"></property>
</bean>
数组注入
<bean class="org.javagirl.ioc.model.User" id="user4">
    <property name="id" value="2"></property>
    <property name="username" value="2"></property>
    <property name="address" value="2"></property>
    <property name="cat" ref="cat"></property>
    <property name="cats">
        <array>
            <ref bean="cat"/>
            <bean class="org.javagirl.ioc.model.Cat" id="cat2">
                <property name="name" value="xiaoxiao"></property>
                <property name="age" value="4"></property>
            </bean>
        </array>
    </property>
    <property name="favorites">
        <list>
            <value>说的话</value>
            <value>比如</value>
        </list>
    </property>
</bean>
<bean id="cat" class="org.javagirl.ioc.model.Cat">
    <property name="name" value="xiaoxiao"></property>
    <property name="age" value="4"></property>
</bean>
map注入
properties注入
<bean class="org.javagirl.ioc.model.User" id="user4">
    <property name="id" value="2"></property>
    <property name="username" value="2"></property>
    <property name="address" value="2"></property>
    <property name="cat" ref="cat"></property>
    <property name="cats">
        <array>
            <ref bean="cat"/>
            <bean class="org.javagirl.ioc.model.Cat" id="cat2">
                <property name="name" value="xiaoxiao"></property>
                <property name="age" value="4"></property>
            </bean>
        </array>
    </property>
    <property name="favorites">
        <list>
            <value>说的话</value>
            <value>比如</value>
        </list>
    </property>
    <property name="details">
        <map>
            <entry key="gender" value="女"></entry>
            <entry value="232" key="age"></entry>
        </map>
    </property>
    <property name="info">
        <props>
            <prop key="phone">132333</prop>
        </props>
    </property>
</bean>
<bean id="cat" class="org.javagirl.ioc.model.Cat">
    <property name="name" value="xiaoxiao"></property>
    <property name="age" value="4"></property>
</bean>

java配置

  • xml注入
  • java配置(java代码将bean注册到容器中)
  • 自动化扫描

springboot中使用java配置开发,不使用xml配置

//表示这是一个java配置类,类似于applicationContext.xml
@Configuration
public class JavaConfig {
    @Bean
    SayHello sayHello(){
        return new SayHello();
    }
}
public class JavaConfigTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class);
        SayHello sayHello = ctx.getBean("sayHello", SayHello.class);
        System.out.println(sayHello.sayHello("javagirl"));
    }
}

自动化配置

包扫描

准备

@Service作为一个标记

@Component 其它组件

@Controller

@Repository Dao层

java代码配置自动扫描
  1. 定义Service @Service

  2. Config配置文件中定义包扫描

    @Configuration
    @ComponentScan(basePackages = "org.javagirl.ioc.service")
    
  3. 获取对象并测试

Bean的名字是类名首字母小写,自定义在@service(“名字”)

扫描按照包的位置扫描可以定义过滤字段

xml配置自动化扫描
  1. 定义Service

  2. xml文件中定义component-scan

对象注入
  1. @Autowired

    根据类型去查找,然后赋值,这个类型只可以有一个对象,否则就会报错

    dao文件

    @Repository
    public class UserDao {
        public String hello(){
            return "hello";
        }
    }
    
    @Service
    public class UserService {
        @Autowired
        UserDao userDao;
    
  2. @Resources

    根据名称去查找,默认情况下,定义的变量名就是查找的名称。如果一个类存在多个实例,使用该注入方式进行注入。@Autowired需要和@Qualifier(指定变量名)配合使用

  3. @Injected

    较少使用

条件注解

满足在某一个条件的情况下,生效的配置

条件注解

@Conditional()

多环境切换

开发,生产,测试环境

Profile,底层为条件注解

@Profile

Main:

ctx.getEnvironment().setActiveProfiles("dev");
@Bean
@Profile("dev")
DataSource devDs(){
    DataSource ds = new DataSource();
    ds.setUrl("jdbc:mysql:///vhr");
    ds.setPassword("root");
    ds.setUsername("root");
    return ds;
}

@Profile("pro")
@Bean
DataSource proDs(){
    DataSource ds = new DataSource();
    ds.setUrl("jdbc:mysql://172.0.0.1:3307/vhr");
    ds.setPassword("root");
    ds.setUsername("root");
    return ds;
}
xml配置

定义beans,进行配置

其它

Bean的作用域

singleton 默认从spring容器中多次获取的是同一个Bean,单例

scope=“protype” 表示获取多个实例

id和name的区别

id和name都可以给Bean指定一个唯一标识符

name支持取多个名字

混合配置

Java配置+XML配置

在Java配置中引入XML配置

@ImportResource("classpath:applicationContext.xml")

Aware接口

感知捕获,单纯的一个Bean是没有感知

Aware接口可以获取容器的详细信息

@Service
@PropertySource(value="javagirl.properties")
public class AwareService implements BeanNameAware, BeanFactoryAware, ResourceLoaderAware, EnvironmentAware {
    private String beanName;
    private Environment environment;
    private ResourceLoader resourceLoader;

    /**
     * 获取工厂环境
     * @param environment
     */
    @Override
    public void setEnvironment(Environment environment) {
        this.environment=environment;
    }


    public void output() throws IOException {
        System.out.println("beanName = " + beanName);
        Resource resource = resourceLoader.getResource("javagirl.txt");
        BufferedReader br = new BufferedReader(new InputStreamReader(resource.getInputStream()));
        String s = br.readLine();
        System.out.println("s = " + s);
        br.close();
        String address = environment.getProperty("javagirl.address");
        System.out.println("address = " + address);
    }

    /**
     * 获取bean的生成工厂
     * @param beanFactory
     * @throws BeansException
     */
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {

    }

    /**
     * 获取bean的名字
     * @param s
     */
    @Override
    public void setBeanName(String s) {
        this.beanName=s;
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader=resourceLoader;
    }
}

Aop

Aop,面向切面编程,对面向对象思想的补充

在不改变源码的情况下,动态的增强方法的功能

日志,事务,数据库操作等

  • 切点:添加代码的地方
  • 通知(增强):想切点动态添加的代码
  • 切面:切面+通知
  • 连接点:切点的定义

Aop的实现

基于Java动态代理的实现

实现:

  • cglib
  • jdk

动态代理

方法增强

public class CalculatorProxy {
    public static Object getInstance(MyCalculatorImpl myCalculator){
        return Proxy.newProxyInstance(CalculatorProxy.class.getClassLoader(), myCalculator.getClass().getInterfaces(), new InvocationHandler() {
            /**
             *
             * @param proxy 代理对象
             * @param method 代理方法
             * @param args 方法参数
             * @return
             * @throws Throwable
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println(method.getName()+":方法开始执行");
                Object invoke = method.invoke(myCalculator, args);
                System.out.println(method.getName()+":方法执行结束");
                return invoke;
            }
        });
    }
}

五种通知

  • 前置通知
@Component
@Aspect
public class LogAspect {
    /**
     * 前置通知
     * @param joinPoint
     */
    @Before("@annotation(Action)")
    public void before(JoinPoint joinPoint){
        String name = joinPoint.getSignature().getName();
        System.out.println("add方法开始执行了");
    }
}
  • 后置通知
/**
 * 后置通知,在目标方法之后执行
 * @param joinPoint
 */
@After("@annotation(Action)")
public void after(JoinPoint joinPoint){
    String name = joinPoint.getSignature().getName();
    System.out.println(name+"方法执行结束了");
}
  • 异常通知
/**
 * 异常通知:当目标方法抛出宜昌市,该方法会被触发
 * @param joinPoint
 * @param e 异常参数,和方法参数名一一对应,注意异常类型,Exception
 */
@AfterThrowing(value= "@annotation(Action)",throwing = "e")
public void afterThrowing(JoinPoint joinPoint,Exception e){
    String name = joinPoint.getSignature().getName();
    System.out.println(name+"方法异常通知"+e.getMessage());
}
  • 返回通知
 /**
     * 返回通知,参数类型匹配时有返回通知,Object可以匹配所有类型
     * @param joinPoint
     * @param r 返回的参数名称,和方法的参数名一一对应
     */
    @AfterReturning(value = "@annotation(Action)",returning = "r")
    public void returning(JoinPoint joinPoint,Object r){
        String name = joinPoint.getSignature().getName();
        System.out.println(name+"方法返回通知"+r);

    }


  • 环绕通知
     @Around("@annotation(Action)")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        //类似于method.invoke方法,可以在这个方法的前后分别添加日志,相当于前置/后置通知
        Object proceed = pjp.proceed();

        return proceed;
    }

通过方法定义切点

@Pointcut("@annotation(Action)")
public void pointcut(){

}

另一种方法

@Pointcut("execution(* aop.service.*.*(..))")
public void pointcut(){

}

xml配置aop

JdbcTemplate

JdbcTemplate时Spring利用Aop思想封装的Jdbc操作工具

配置jdbc

java配置
xml配置

事务

利用Aop思想,简化事务的配置,可以通过java配置也可以通过XML配置

XML配置
  1. 配置事务管理器
  2. 配置事务处理的方法
  3. 配置aop
java代码

@Transactional 注解

上一篇:SpringBoot整合AOP超详细教程


下一篇:spring 中使用 @Aspect 注解实现 aop 切面