Spring

Spring

一、spring核心内容

1、IOC

IOC:控制反转。控制权反转给spring。

之前对象的创建是由程序员完成的,用了spring之后,对象的创建教给了spring容器。spring可以帮助我们管理bean对象。

如何使用spring

<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>5.3.5</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>5.3.5</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.3.5</version>
    </dependency>

创建beans.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="users" class="com.openlab.beans.Users"></bean>
</beans> 

使用

 public void test02(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        Object obj =  applicationContext.getBean("users");//通过id获取
        System.out.println(obj);
        Users users =  applicationContext.getBean("users",Users.class);//通过id和类型
        System.out.println(users);
        System.out.println(users.getUsername()+"\t"+users.getPassword()+"\t"+users.getStatus());
        Users users01 =  applicationContext.getBean(Users.class);//通过类型获取,要求spring容器中只能有唯一的改类型的bean对象
​
        System.out.println(users01);
 }

spring给对象的属性赋值

1、set注入:直接调用set方法

2、构造子注入:

<bean id="users01" class="com.openlab.beans.Users">
       <constructor-arg  value="1" ></constructor-arg>
       <constructor-arg  value="2"></constructor-arg>
</bean>
<bean id="users01" class="com.openlab.beans.Users">
       <constructor-arg  value="1" name="status" ></constructor-arg>
       <constructor-arg  value="2" name="password"></constructor-arg>
</bean>
<!--
改类中有两个参数的构造方法
-->
​
<!--调用有一个参数的构造方法,如果有多个一个参数的构造方法,咱们给status属性的构造方法执行-->
 <bean id="users01" class="com.openlab.beans.Users">
        <constructor-arg name="status" value="1"></constructor-arg>
        <property name="username" value="test01"></property>
</bean>
<!--
 ref:指向spring容器中的另一个bean对象
-->

3、接口注入(DI)

DI:依赖注入,service依赖dao.将dao的创建给了spring容器。

@Getter
@Setter
public class UsersServiceImpl {
    private UsersDao usersDao ;
​
    public void save(){
        Users users = new Users();
        usersDao.save(users);
        System.out.println("---service中的添加方法---");
    }
}
​
    <bean  id="userDaoImpl1" class="com.openlab.dao.impl.UsersDaoImpl"></bean>
     <bean  id="userDaoImpl2" class="com.openlab.dao.impl.UsersDaoImpl2"></bean>
     <bean id="userService" class="com.openlab.service.UsersServiceImpl">
          <property name="usersDao" ref="userDaoImpl2"></property>
     </bean>

4、内部bean

 <bean id="emp3" class="com.openlab.beans.Emp">
        <property name="empid" value="1003"></property>
        <property name="empname" value="juddy"></property>
        <property name="dept">
            <!--内部bean的定义,使用只能再给emp3中的dept属性赋值
              可以给id属性赋值,该bean再其他的地方也是不能使用的。
             -->
            <bean class="com.openlab.beans.Dept" id="dept">
                <property name="deptname" value="测试部"></property>
            </bean>
        </property>
    </bean>

5、集合属性赋值

@Getter
@Setter
@NoArgsConstructor
public class CollectionTest {
    private String[] arr;
    private List<String> list;
    private Map<String,String> map;
    private Set<String> set;
​
    private List<Emp> emps;
    private Map<String,Emp> empMap;
}
​
 <bean id="collectionTest" class="com.openlab.beans.CollectionTest">
         <property name="arr">
                <array>
                     <value>arr01</value>
                     <value>arr02</value>
                     <value>arr03</value>
                </array>
         </property>
         <property name="list">
               <list>
                    <value>list01</value>
                    <value>list02</value>
                    <value>list03</value>
               </list>
         </property>
         <property name="map">
               <map>
                     <entry key="zh" value="中国"></entry>
                     <entry key="jp" value="日本"></entry>
                     <entry key="us" value="美国"></entry>
               </map>
         </property>
         <property name="set">
               <set>
                    <value>set01</value>
                    <value>set02</value>
                    <value>set03</value>
               </set>
         </property>
         <property name="emps" ref="emplist">
             <!-- <list>
                   <ref bean="emp"></ref>
                   <ref bean="emp2"></ref>
                   <ref bean="emp3"></ref>
              </list>-->
         </property>
         <property name="empMap">
               <map>
                    <entry key="1001" value-ref="emp"></entry>
                    <entry key="1002" value-ref="emp2"></entry>
                    <entry key="1003" value-ref="emp3"></entry>
               </map>
         </property>
     </bean>
​
    <bean class="com.openlab.beans.Emp" id="emp">
        <property name="empid" value="1001"></property>
        <property name="empname" value="jerry"></property>
    </bean>
    <bean class="com.openlab.beans.Emp" id="emp2">
        <property name="empid" value="1002"></property>
        <property name="empname" value="lucy"></property>
    </bean>
    <bean id="emp3" class="com.openlab.beans.Emp">
        <property name="empid" value="1003"></property>
        <property name="empname" value="juddy"></property>
        <property name="dept">
            <!--内部bean的定义,使用只能再给emp3中的dept属性赋值-->
            <bean class="com.openlab.beans.Dept">
                <property name="deptname" value="测试部"></property>
            </bean>
        </property>
    </bean>
​
    <util:list id="emplist">
         <ref bean="emp"/>
         <ref bean="emp2"/>
         <ref bean="emp3"/>
    </util:list>

如果使用util:list必须加入头部信息

<?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:c="http://www.springframework.org/schema/c"
       xmlns:util="http://www.springframework.org/schema/util"
       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
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd">
   
    
</beans>    

6、Bean工厂

public class MyFactoryBean implements FactoryBean<Emp> {
    @Override
    public Emp getObject() throws Exception {
       Emp emp =   new Emp();
       emp.setEmpid(1001);
       emp.setEmpname("工厂bean创建的bean");
        return emp;
    }
​
    @Override
    public Class<?> getObjectType() {
        return Emp.class;
    }
}
​
   <bean id="myFactoryBean" class="com.openlab.beans.MyFactoryBean"></bean>
   @Test
    public void test16(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beans06.xml");
        MyFactoryBean factoryBean =  context.getBean(MyFactoryBean.class);
        System.out.println(factoryBean);
​
       Emp emp =    context.getBean("myFactoryBean",Emp.class);//获取员工的信息
        System.out.println(emp);
​
    }

7、Bean的作用域[是否是单例]

    <!--
    prototype:非单例模式
    prototype:单例模式 默认值
    -->
    <bean id="users" class="com.openlab.beans.Users" scope="prototype|singleton">
        <property name="username" value="admin"></property>
        <property name="password" value="admin123"></property>
        <property name="status" value="1"></property>
        <property name="usersInfo" ref="userinfo"></property>
    </bean>

8、Bean的生命周期

1>构造

2>set

3>初始化

4>bean可以正常使用

5>销毁

<!--
init-method:初始化方法
destroy-method:销毁的方法
-->
<bean id="beanLife" class="com.openlab.beans.BeanLife" init-method="init" destroy-method="destroy">
         <property name="name" value="生命周期"></property>
    </bean>
@Test
    public void test17(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans06.xml");
​
        BeanLife emp =    context.getBean(BeanLife.class);
        System.out.println(emp);
        context.close();//context进行close 的时候,才会执行destroy方法
​
    }

bean的生命周期 七部

1>构造

2>set

3>初始化方法之前

4>初始化方法

5>初始化方法之后

6>bean可以正常使用

7>销毁

使用步骤 1>定义BeanPostProcessor类

public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化前");
        return bean;
    }
​
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化后");
        return bean;
    }
}
​

2>将以上定义的类交给spring管理

<bean id="myBeanPostProcessor" class="com.openlab.beans.MyBeanPostProcessor"></bean>
    <bean id="beanLife" class="com.openlab.beans.BeanLife" init-method="init" destroy-method="destroy">
         <property name="name" value="生命周期"></property>
    </bean>

3>测试 加载以上beans.xml文件的时候,里面所有的bean都会执行定义的生命周期中的方法

@Test
    public void test17(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans06.xml");
        BeanLife emp =    context.getBean(BeanLife.class);
        System.out.println(emp);
        context.close();
​
    }

9、自动装配

<bean  id="userDaoImpl1" class="com.openlab.dao.impl.UsersDaoImpl"></bean>  
<bean id="userService" class="com.openlab.service.UsersServiceImpl" autowire="byType"></bean>
<!--
autowire="byName"  可以定义多个dao对象,会将id和属性名相同的 对象赋值给属性
autowire="byType"  只能定义一个dao对象,将该dao实例赋值给属性  
-->

10、引入资源文件

druid.properties

druid.driverClassName:com.mysql.cj.jdbc.Driver
druid.url:jdbc:mysql:///test?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true
druid.name:root
druid.password:123456
<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:c="http://www.springframework.org/schema/c"
       xmlns:util="http://www.springframework.org/schema/util"
       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
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd">
    
    <context:property-placeholder location="classpath:druid.properties"></context:property-placeholder>
   <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
       <property name="username" value="${druid.name}"></property>
       <property name="url" value="${druid.url}"></property>
       <property name="password" value="${druid.password}"></property>
       <property name="driverClassName" value="${druid.driverClassName}"></property>
   </bean>
</beans>

练习:

1>整理笔记,知识点整理出来,知识点对应的练习【博客】

11、注解的使用

1>xml文件中添加要扫描的基本包

 <context:component-scan base-package="org.openlab"/>

2>类中添加注解,代表该类已经被spring管理

@Component//普通的java类
@Repository//持久层,dao层
@Service//业务层 service层
@Controller //控制层 servlet,mvc

spring管理bean的时候,默认给bean起别名,别名教 类名首字母小写。

通过以上注解的value属性给对象起别名

@Getter
@Setter
@Component(value = "userinfo")//不使用value属性,该类的对象名教users。如果使用value属性就是给类起新的名字:userinfo
public class Users {
    private Integer userid;
    private String username;
    private String password;
​
}
<context:component-scan base-package="org.openlab">
           <!--不包含Controller注解,spring会管理基础包下的所有的类,但是不包含Controller注解-->
         <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<context:component-scan base-package="org.openlab" use-default-filters="false">
         <!--只包含Controller注解,必须不能使用默认的filter,use-default-filters="false"-->
           <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
     </context:component-scan>

自动注入,action依赖service.在action中直接通过@Autowired注解给属性注入值

 @Autowired 
@Controller
public class UsersAction {
    @Autowired
    private UsersService usersService;
​
    public void save(){
        Users users = new Users();
        usersService.save(users);
    }
}

如果一个接口对应多个实现类的时候,此时使用@Autowired不知道将哪个实现类注入进进去,此时借助@Qualifier 来指定注入的是哪个对象

​
@Service
public class UsersServiceImpl implements UsersService {
    @Qualifier(value = "usersDaoImpl2")//指定拿一个实现类注入信息的
    @Autowired
    private UsersDao usersDao ;
​
    @Override
    public void save(Users users) {
        System.out.println("service层中的save方法执行了");
        usersDao.save(users);
    }
}
​

@Resource :是将name指定的对象注入到属性中。等价与@Autowired与@Qualifier综合

/*  @Qualifier(value = "usersDaoImpl2")//指定拿一个实现类注入信息的
  @Autowired*/
  @Resource(name = "usersDaoImpl2")
  private UsersDao usersDao ;

@Value 注入值

@Getter
@Setter
@Component
public class Users {
    @Value("1001")
    private Integer userid;
    @Value("admin")
    private String username;
    @Value("123456")
    private String password;
​
}

12、完全注解,不依赖配置文件

1>普通的java类充当配置信息

@Configuration
@ComponentScan(value = {"org.openlab"})
public class SpringConfig {
}

2>测试,创建的对象是 AnnotationConfigApplicationContext

   @Test
    public void test01(){
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        UsersAction usersAction =  context.getBean(UsersAction.class);
        usersAction.save();
    }

作业> spring管理bean对象

1>创建类

public class Car {
​
    private String brand;
    private String corp;
    private double price;
    private int maxpeed;
    public Car(String brand, String corp, double price) {
        super();
        this.brand = brand;
        this.corp = corp;
        this.price = price;
    }
    
    public Car(String brand, String corp, int maxpeed) {
        super();
        this.brand = brand;
        this.corp = corp;
        this.maxpeed = maxpeed;
    }
​
    @Override
    public String toString() {
        return "Car [brand=" + brand + ", corp=" + corp + ", price=" + price + ", maxpeed=" + maxpeed + "]";
    }
    
    
}

将该类教给spring管理,同时

1) 借助set给属性注入值

2)借助构造方法给属性注入值。【两个都是三个参数的构造方法】

2>创建类,包含集合属性,如何给以下集合属性注入信息

public class CollectionTest {
    private String[] arr;
    private List<String> list;
    private Map<String,String> map;
    private Set<String> set;
​
    private List<Emp> emps;
    private Map<String,Emp> empMap;
}
​

3>创建部门和员工类

public class Dept{
    private Integer deptid;
    private String deptname;
    private String deptdesc;
    private List<Emp> list;
}
public class Emp{
    private Integer empid;
    private String empname;
    private String empsex;
    private Dept dept;
​
}

将类交给spring管理,给dept中的list集合赋值.一种list赋值。util:list

emp:给emp中的dept赋值

4>注解的练习:【熟练掌握】

创建Service以及Dao service依赖dao 。自动注入dao.

dao又多了一个实现类,如何注入?

5>纯注解,不需要配置文件

2、AOP

OOP:面向对象

AOP:面向切面编程

实现:

1>普通的类,教给spring管理

​
@Component
public class UsersDaoImpl {
​
        public void save(){
            System.out.println("userDao中实现类1的save");
        }
        public Integer update(Users user) {
            System.out.println("dao实现类1执行了。。。"+user);
            return 10;
        }
        public Integer test(int a, int b) {
            System.out.println("dao实现类1执行了。。。。");
            return a+b;
        }
​
}
​

2>定义aspect类, 该类也是需要教给spring管理的,同时是要给@Aspect类

​
@Component
@Aspect// AopPoxy是一个切面类,需要交给spring管理
public class AopProxy {
    //切入点:pointcut
    //before:通知的类型 前置通知
    @Before("execution(* com.openlab.aop.UsersDaoImpl.save())")//* com.openlab.aop.UsersDaoImpl.save():连接点
    public void beforeMethod(){
        System.out.println("在方法执行之前要执行的代码");
    }
}

该类是要给切面类,称为aspect类

需要对哪个方法进行增强,需要对UsersDaoImpl.save() 方法做增强,该方法就称为链接点

需要对save方法增强的方法,成功称为切入点。

在save方法什么时机增强,通知的类型,前置通知,后置通知,环绕通知,最终通知,异常通知

环绕方法之前 @Around

前置通知 @Before

最终通知 @AfterReturning|异常通知@AfterThrowing

后置通知@After

环绕方法之后@Around

@Component
@Aspect// AopPoxy是一个切面类,需要交给spring管理
@Order(0)
public class AopProxy02 {
   @Pointcut("execution(* com.openlab.aop.*.*.*(..))")
    public void mypoint(){
​
    }
    //切入点:pointcut
    //before:通知的类型 前置通知
    @Before(value = "execution(* com.openlab.aop.*.*.*(..))")//* com.openlab.aop.impl1.UsersDaoImpl.save():连接点
    public void beforeMethod(){
        System.out.println("第0个代理对象中的前置通知::在方法执行之前要执行的代码");
    }
   @After(value = "execution(* com.openlab.aop.*.*.*(..))")
    public void afterMethod(){
        System.out.println("后置通知:方法之前之后要执行的代码");
    }
​
    @AfterReturning(value = "execution(* com.openlab.aop.*.*.*(..))")
    public void returnMethod(){
        System.out.println("最终通知:");
    }
    @AfterThrowing(value = "execution(* com.openlab.aop.*.*.*(..))")
    public void exectionMethod(){
        System.out.println("异常通知:");
    }
   @Around(value = "execution(* com.openlab.aop.*.*.*(..))")
    public void roundMethod(ProceedingJoinPoint joinPoint){
        System.out.println("环绕方法之前");
       try {
           joinPoint.proceed();//继续执行你的方法
       } catch (Throwable throwable) {
           throwable.printStackTrace();
       }
       System.out.println("环绕方法之后");
    }
}

可以抽取pointcut():切入点

@Component
@Aspect// AopPoxy是一个切面类,需要交给spring管理
@Order(0)//如果有多个代理的时候,哪个先执行,可以通过order定义,数字越小越先执行
public class AopProxy02 {
   @Pointcut("execution(* com.openlab.aop.*.*.*(..))")
    public void mypoint(){
​
    }
    //切入点:pointcut
    //before:通知的类型 前置通知
    @Before(value = "mypoint()")//* com.openlab.aop.impl1.UsersDaoImpl.save():连接点
    public void beforeMethod(){
        System.out.println("第0个代理对象中的前置通知::在方法执行之前要执行的代码");
    }
   @After(value = "mypoint()")
    public void afterMethod(){
        System.out.println("后置通知:方法之前之后要执行的代码");
    }
​
    @AfterReturning(value = "mypoint()")
    public void returnMethod(){
        System.out.println("最终通知:");
    }
    @AfterThrowing(value = "mypoint()")
    public void exectionMethod(){
        System.out.println("异常通知:");
    }
   @Around(value = "mypoint()")
    public void roundMethod(ProceedingJoinPoint joinPoint){
        System.out.println("环绕方法之前");
       try {
           joinPoint.proceed();//继续执行你的方法
       } catch (Throwable throwable) {
           throwable.printStackTrace();
       }
       System.out.println("环绕方法之后");
    }
}

注解的方式

1>定义两个类

public class AopProxy {
    public void beforeMehtod(){
        System.out.println("方法执行之前");
    }
    public void afterMehtod(){
        System.out.println("方法执行之后");
    }
    public void afterRuturning(){
        System.out.println("最终通知,返回通知");
    }
​
}
​
​
public class EmpDaoImp {
​
    public void save(String name){
        System.out.println("empDao类中的save方法");
        if(name.equals("error")){
            throw  new RuntimeException("名字含有特殊字符");
        }
    }
}
​

通过配置的方式实现aop

  <bean id="empDao" class="com.openlab.annocation.EmpDaoImp"></bean>
  <bean id="aopProxy" class="com.openlab.annocation.AopProxy"></bean>
<aop:config>
          <aop:pointcut id="mypoint2" expression="execution(* com.openlab.annocation.*.*(..))"/><!--pointcut:切入点-->
           <aop:aspect ref="aopProxy"> <!--切面类-->
                <aop:before method="beforeMehtod" pointcut-ref="mypoint2"></aop:before>
               <aop:after method="afterMehtod" pointcut-ref="mypoint2"></aop:after>
               <aop:after-returning method="afterRuturning" pointcut-ref="mypoint2"></aop:after-returning>
           </aop:aspect>
</aop:config>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值