Spring

1.Spring是一个分层的全栈式轻量级开发框架,以IOC和AOP为核心
2.IOC控制反转将创建对象的工作交给Spring框架。DI依赖注入负责具体实现创建对象的过程
3.导入jar包后,根据需求配置xml文件

public interface Dao {
    public void excute();
}

public class DaoImpl1 implements Dao{
    @Override
    public void excute() {
        System.out.println("DaoImpl1");
    }
}

<?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="DaoImpl1" class="Dao.DaoImpl1">


    </bean>

</beans>
创建对象:
        ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        Dao dao=(Dao) context.getBean("DaoImpl1");
        dao.excute();
需要变更直接将xml文件中,<bean>标签属性中class的值改变即可,不需要改动代码

4.bean标签属性详解
id:定位对象唯一标识
class:定位要创建对象的类所在位置
lazy-init:默认false,懒加载。初始化时就已经把配置文件的对象创建好并收入到容器中。配为true,则在调用getBean方法时才会创建
scope:  singlon(默认) - 单例
        prototype - 多例
        request - 每一次http请求都会生成一个对象,仅在当前请求有效,请求完毕随即销毁。
        session - 每一次http请求都会生成一个对象,仅在当前session有效,session销毁对象随即销毁。
init-method:指定对象初始化时需要执行的方法
autowire:   byName 通过对象中属性名寻找容器中id一致的属性进行注入
            byType 通过对象中属性类型寻找容器中class一致的属性进行注入(将要注入的属性在容器中声明只允许纯在一个)

5.可以通过构造方法注入对象的属性值
public class Person {
    private Integer userid;
    private String username;
    private String password;

    @Override
    public String toString(){
        String result = "User:{userid="+userid+",username="+username+",password="+password+"}";
        return result;
    }

    public Person(){

    }

    public Person(Integer userid, String username, String password) {
        System.out.println("BuildPerson");
        this.userid = userid;
        this.username = username;
        this.password = password;
    }

    public void setUserid(Integer userid) {
        System.out.println("setUserid");
        this.userid = userid;
    }

    public void setUsername(String username) {
        System.out.println("setUsername");
        this.username = username;
    }

    public void setPassword(String password) {
        System.out.println("setPassword");
        this.password = password;
    }
}

public class Company {
    Person p;

    public void setP(Person p) {
        this.p = p;
    }
}

    <bean id="person2" class="Entity.Person">
        <constructor-arg name="userid" value="2"/>
        <constructor-arg name="username"  value="cccc"/>
        <constructor-arg name="password"  value="dddd"/>
    </bean>

当对象属性存在set方法时,可以通过<property></property>标签注入
    <--对象person>
    <bean id="person" class="Entity.Person">
        <!--文本注入,可以忽略特殊字符-->
        <property name="userid">
                    <value><![CDATA[11]]></value>
        </property>
        <property name="username" value="aaaa"></property>
        <property name="password">
            <value>bbbb</value>
        </property>
    </bean>

    <--对象Company>
     <bean id = "company" class="Entity.Company">
        <!-- 引用类型注入 -->
        <property name="p">
            <bean id = "person" class = "Entity.Person"></bean>
        </property>
        <!-- 数组注入 -->
        <property name="arr">
            <array>
                <value>1</value>
                <value>2</value>
            </array>
        </property>

        <!-- list注入基础类型 -->
        <property name="list">
            <list>
                <value>JAVA</value>
                <value>JAVA</value>
            </list>
        </property>

        <!-- list注入引用类型 -->
        <property name="listObj">
            <list>
                <bean id = "person11" class="Entity.Person"></bean>
                <bean id = "person22" class="Entity.Person"></bean>
                <ref bean="person"></ref>
            </list>
        </property>

        <!-- set注入基础类型 -->
        <property name="set">
            <set>
                <value>1</value>
                <value>2</value>
            </set>
        </property>

        <!-- set注入引用类型 -->
        <property name="setObj">
            <set>
                <bean id = "person33" class="Entity.Person"></bean>
                <bean id = "person44" class="Entity.Person"></bean>
                <ref bean="person"></ref>
            </set>
        </property>

        <!-- map注入基础类型 -->
        <property name="map">
            <map>
                <entry key="1" value="1"></entry>
                <entry key="2" value="2"></entry>
                <entry key="3" value="3"></entry>
            </map>
        </property>

        <!-- map注入引用类型-->
        <property name="mapObj">
            <map>
                <entry key-ref="person" value-ref="person2"></entry>
                <entry>
                    <key>
                        <bean id = "person55" class="Entity.Person">
                            <property name="userid" value="55"></property>
                        </bean>
                    </key>
                    <bean id = "person66" class="Entity.Person">
                        <property name="userid" value="66"></property>
                    </bean>
                </entry>
            </map>
        </property>

    </bean>

6.自建工厂
import org.springframework.beans.factory.FactoryBean;

/**
* 自建工厂,实现FactoryBean接口
*/
public class CompanyFactory implements FactoryBean<Company> {
    @Override
    public Company getObject() throws Exception {
        System.out.println("通过自建工厂返回实例");
        return new Company();
    }

    @Override
    public Class<?> getObjectType() {
        return Company.class;
    }
}

/**
* 配置文件
*/
<bean id="company2" class="Entity.CompanyFactory"></bean>

/**
* 创建对象代码
*/
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Company company = context.getBean("company2",Company.class);
执行结果:
通过自建工厂返回实例

可以看到,配置文件虽然注入的是CompanyFactory类,返回的确是company对象。其实这一步本质上也是框架替我们做的。

6.Bean的生命周期
1.配置对象
2.注入属性
3.执行初始化方法
4.获得对象
5.销毁对象

如果想对全局对象在初始化方法执行前/执行后添加操作,可以配置一个或多个后置处理器(类似于代理模式)
/**
* 后置处理器
*/
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化方法执行前");
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化方法执行后");
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

    <!-- 注册后置执行器-->
    <bean id="mybeanpostprocessor1" class="Entity.MyBeanPostProcessor"></bean>

7.Spring引入外部配置文件
首先需要引入context命名空间
新增
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"
变成
        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"
配置文件内容
test_userid=1
test_username=aaa
test_password=bbb

<!--引入配置文件-->
<context:property-placeholder location="classpath:test.properties"></context:property-placeholder>
<!--注入属性-->
<bean id="person" class="Entity.Person">
    <property name="userid" value="${test_userid}"></property>
    <property name="username" value="${test_username}"></property>
    <property name="password" value="${test_password}"></property>
</bean>

8.注解实现IOC和DI
注解实现创建对象可以免去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"
       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="Annotation"></context:component-scan>

</beans>

8 类注解:使用该注解的类都可以通过容器创建对象
@Component :通用注解
@Controller:Controller层注解
@Service:Service层注解
@Repository:持久化层注解

/**
* 自定义id,默认id类名首字母小写,下面例子就是testController
*/
@Controller("tesController")
public class TestController {
    public TestController() {
        System.out.println(1);
    }
}

可以通过配置XML文件指定扫描的注解范围

    <!--  
    use-default-filters:false不启用默认过滤器
     <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        :扫描Controller类型注解
     <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
        :不扫描Service注解
    -->
    <context:component-scan base-package="Annotation" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
    </context:component-scan>

获得对象

        //获得配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("Annotation.xml");
        //获得对象,ID是注解所在的类的类名首字母小写,也可以自定义id
        TestController controller = context.getBean("testController",TestController.class);

通过注解实现DI
@Service
public interface UserService {
    void add();
}

@Service
public class UserServiceImpl implements UserService {
    
    @Autowired
    UserDao userDao;

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

@Repository
public interface UserDao {
    void add();
}

@Repository
public class UserDaoImpl1 implements UserDao {
    @Override
    public void add() {
        System.out.println("UserDapImpl1");
    }
}

@Autowired:自动注入属性,当该属性在扫描范围内只有一个实现类时才能使用,当有多个实现类时,需要再加上@Qualifier("userDaoImpl2")注解指定实现类名称

@Repository
public class UserDaoImpl2 implements UserDao {
    @Override
    public void add() {
        System.out.println("UserDapImpl2");
    }
}

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    @Qualifier("userDaoImpl2")
    UserDao userDao;

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

@Resource(name="userDaoImpl2");可以实现一个注解完成上面两个注解的工作,如果只有一个实现类则不需要指定名字,但这个注解是javax.annotation包下的,不是spring的

基础属性赋值:通过value注解
    @Value("111")
    private String str1;
    @Value("${test_str2}")
    private String str2;

    <context:property-placeholder location="annotation.properties"></context:property-placeholder>

9.AOP
AOP是Spring的利用动态代理实现面向切面编程,随时可以在执行A方法之前/之后添加新的方法

9.1 术语解析
连接点(joint point): 原始对象中允许被增强的方法。
切入点(PointCut): 原始对象中实际被增强的方法。
通知(Advice): 代理对象中新加入的功能
    通知类型:
        前置通知:切入点前执行的通知
        后置通知:切入点后执行的通知,切入点执行异常则不执行后置通知
        环绕通知:切入点前后都要执行的通知
        异常通知:切入点发生异常时要执行的通知
        最终通知:在切入点执行完毕之后执行的通知,无论是否发生异常
目标对象(Target): 被增加功能的对象(被代理对象)
切面(Aspect): 将所有通知组合成一个类,就是切面。每个通知都要指定自己的切入点范围
织入(Weaving): 生成代理对象并执行代理方法的过程
切入点表达式:通过表达式指定切入点的位置,用于建立通知和切入点之间的联系
excution([权限修饰符] [返回值类型(可以省略)] [类的全路径名] [方法名] [参数列表])
excution(* com.aop.User.add(..)) 切入User类的add方法上
excution(* com.aop.User.*(..)) 切入User类的所有方法上
excution(* com.aop.*.*(..)) 切入aop包内所有类的所有方法上
excution(* com.aop.*.add(..)) 切入aop包内所有类的add方法上
excution(* com.aop.*.add*(..)) 切入aop包内所有类的以add开头的方法上

9.2 注解实现AOP
package com.Aop;
/**
 * 目标对象
 **/
@Component
public class User {

    public int add(){
        return 1;
    }

    public int add(int i){
        return i+1;
    }

    public int add(int i,String value){
        System.out.println(value);
        return i+1;
    }
}

package com.Aop;

/**
 * 切面
 * */
@Aspect
@Component
public class Advices {

    //定义公共切点
    @Pointcut("execution(* com.Aop.User.add(int ,String))")
    private void addPointCut(){}

    //前置通知
    @Before("execution(* com.Aop.User.add(int ,String))")
    public static void addBefore(JoinPoint joinPoint){
        //获取切入点的实参
        Object[] args = joinPoint.getArgs();
        System.out.println("日志开始");
    }

    //最终通知,是否异常都会执行
    @After("execution(* com.Aop.User.add(int ,String))")
    public static void addAfter(JoinPoint joinPoint){
        //获取切入点的实参
        Object[] args = joinPoint.getArgs();
        System.out.println("日志结束");
    }

    //返回通知(可以拿到切入点的返回值),异常则不会执行
    @AfterReturning(value = "execution(* com.Aop.User.add(int ,String))",returning = "res")
    public static void addAfterRetrunning(JoinPoint joinPoint,Object res){
        //获取切入点的实参
        Object[] args = joinPoint.getArgs();
        System.out.println("日志结束");
    }

    //异常通知
    @AfterThrowing(value = "execution(* com.Aop.User.add(int ,String))",throwing = "e")
    public static void addExecept(Exception e){

        System.out.println("日志结束");
    }

    //环绕通知,此处引入了公共切点
    @Around("addPointCut()")
    public static void addAround(ProceedingJoinPoint proceedingJoinPoint){
        System.out.println("日志开始");
        try {
            //控制切入点执行
            proceedingJoinPoint.proceed();
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
        System.out.println("日志结束");
    }

}


配置文件
<?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: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/aop
                           http://www.springframework.org/schema/aop/spring-aop.xsd">

    <context:component-scan base-package="com"></context:component-scan>
    <aop:aspectj-autoproxy/>

</beans>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值