Spring 是一个项目管理框架,简化企业级开发,俗称”胶水框架”。
自定义工厂类做类的实例化。
// mypro.properties
userdao=com.baidu.day.text.dao.impl.UserDaoImpl
// MyUtils.java
public class MyUtils {
public static Properties properties = null;
static {
InputStream resourceAsStream = MyUtils.class.getClassLoader().getResourceAsStream("mypro.properties");
properties = new Properties();
try {
properties.load(resourceAsStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static Object getObject(String beanName) {
String property = properties.getProperty(beanName);
try {
Class<?> aClass = Class.forName(property);
return aClass.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
// IUserDao.java
public interface IUserDao {
void show();
}
// UserDaoImpl.java
public class UserDaoImpl implements IUserDao {
@Override
public void show() {
System.out.println("hello spring。");
}
}
// 测试
IUserDao userDao = (UserDaoImpl)MyUtils.getObject("userdao");
userDao.show();
使用 Spring 做类的实例化。
Spring 工厂特性。饿汉式创建。工厂创建之后,会将 Spring 配置文件中的所有对象都创建完成(饿汉式)。提高程序运行效率。避免多次IO,减少对象创建时间。(概念接近连接池,一次性创建好,使用时直接获取)。
// pom.xml
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
</dependencies>
// spring.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="userDao" class="com.baidu.day.text.dao.impl.UserDaoImpl" />
</beans>
// 测试
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
IUserDao userDao = (IUserDao) ac.getBean("userDao");
userDao.show();
IDEA 添加代码模版。
Preferences -> Editor -> File And Code Templates。
单例和多例。
// spring.xml
<!-- scope="prototype" 多例,默认为单例 singleton -->
<bean id="userDao" class="com.baidu.day.text.dao.impl.UserDaoImpl" scope="prototype" />
// 测试
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
IUserDao userDao1 = (IUserDao) ac.getBean("userDao");
IUserDao userDao2 = (IUserDao) ac.getBean("userDao");
IUserDao userDao3 = (IUserDao) ac.getBean("userDao");
System.out.println(userDao1);
System.out.println(userDao2);
System.out.println(userDao3);
控制反转。实际上是类的嵌套实例化。
// IUserService.java
public interface IUserService {
void show();
}
// UserServiceImpl.java
// 注意要写set/get
@Data
public class UserServiceImpl implements IUserService {
private IUserDao userDao;
@Override
public void show() {
userDao.show();
System.out.println("这是 service");
}
}
// spring.xml
<bean id="userDao" class="com.baidu.day.text.dao.impl.UserDaoImpl" scope="prototype" />
// 1
<bean id="userService" class="com.baidu.day.text.service.impl.UserServiceImpl" >
<!-- name 对应实例属性名; ref,引用,对应实例的bean id -->
<property name="userDao" ref="userdao"></property>
</bean>
// 2、3
<!-- autowire 自动写入。byName,根据属性名,引入的bean id 和 属性名要一致;byType,根据属性类型 -->
<bean id="userService" class="com.baidu.day.text.service.impl.UserServiceImpl" autowire="byName">
</bean>
// 测试
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
IUserService userService = (IUserService) ac.getBean("userService");
userService.show();
依赖注入。实际上就是初始化赋值。
@Data
public class Address {
private Integer id;
private String address;
}
// User.java
@Data
public class User {
private Integer id;
private String password;
private String sex;
private Integer age;
private Date bornDate;
private String[] hobbys;
private Set<String> phones;
private List<String> names;
private Map<String,String> countries;
private Properties files;
/* 对象s */
private Address address;
}
// spring.xml 部分代码
<!-- 依赖注入 -->
<bean id="user" class="com.baidu.day.text.entity.User">
<!-- 使用set、get方法赋值 -->
<property name="id" value="1"></property>
<property name="password" value="123"></property>
<property name="sex" value="男"></property>
<property name="age" value="12"></property>
<!-- 日期, 固定格式 xxxx/xx/xx -->
<property name="bornDate" value="2021/1/21"></property>
<!-- 数组 -->
<property name="hobbys">
<array>
<value>coding</value>
<value>read</value>
<value>write</value>
</array>
</property>
<!-- set -->
<property name="phones">
<set>
<value>123</value>
<value>234</value>
</set>
</property>
<!-- list -->
<property name="names">
<list>
<value>admin</value>
<value>张三</value>
</list>
</property>
<!-- map -->
<property name="countries">
<map>
<entry key="cn">
<value>china</value>
</entry>
<entry key="usa">
<value>amarican</value>
</entry>
</map>
</property>
<!-- properties -->
<property name="files">
<props>
<prop key="username">admin</prop>
<prop key="password">123</prop>
</props>
</property>
<!-- 对象 -->
<property name="address">
<bean class="com.baidu.day.text.entity.Address">
<property name="id" value="1"></property>
<property name="address" value="北京"></property>
</bean>
</property>
</bean>
// 测试
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
User user = (User) ac.getBean("user");
System.out.println(user);
构造注入。
// Student.java
public class Student {
private Integer id;
private String name;
private String sex;
private Integer age;
public Student(Integer id, String name, String sex, Integer age) {
this.id = id;
this.name = name;
this.sex = sex;
this.age = age;
}
}
// spring.xml
<!-- 默认调用无参构造方法,没有会报错 -->
<bean id="student" class="com.baidu.day.text.entity.Student">
<!-- 根据参数名 -->
<constructor-arg name="id" value="1"></constructor-arg>
<constructor-arg name="name" value="admin"></constructor-arg>
<constructor-arg name="sex" value="男"></constructor-arg>
<constructor-arg name="age" value="12"></constructor-arg>
<!-- 根据下标 -->
<!-- <constructor-arg index="0" value="1"></constructor-arg>-->
<!-- <constructor-arg index="1" value="admin"></constructor-arg>-->
<!-- <constructor-arg index="2" value="男"></constructor-arg>-->
<!-- <constructor-arg index="3" value="12"></constructor-arg>-->
<!-- 根据参数个数 -->
<!-- <constructor-arg value="1"></constructor-arg>-->
<!-- <constructor-arg value="admin"></constructor-arg>-->
<!-- <constructor-arg value="男"></constructor-arg>-->
<!-- <constructor-arg value="12"></constructor-arg>-->
</bean>
对象初始化和销毁。
// Address.java
@Data
public class Address {
private Integer id;
private String address;
public void init(){
System.out.println("初始化了");
}
public void destroy(){
System.out.println("销毁");
}
}
// spring.xml
<bean id="address" class="com.baidu.day.text.entity.Address" init-method="init" destroy-method="destroy">
<property name="id" value="1"></property>
<property name="address" value="深圳"></property>
</bean>
FactoryBean 创建复杂对象。
// MyConnection.java
public class MyConnection implements FactoryBean<Connection> {
@Override
public Connection getObject() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1", "admin", "admin");
return connection;
}
@Override
public Class<?> getObjectType() {
return Connection.class;
}
// 是否单例
@Override
public boolean isSingleton() {
return false;
}
}
// spring.xml
<!-- 返回的是 getObject 返回的 -->
<bean id="conn" class="com.baidu.day.text.utils.MyConnection"></bean>
// 测试
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
Connection connection = (Connection) ac.getBean("conn");
System.out.println(connection);
代理。就是找个中间人来做事。常用来回调数据。
静态代理。
// IFangDong.java
public interface IFangDong {
void zufang();
}
// FangDongImpl.java
public class FangDongImpl implements IFangDong {
@Override
public void zufang() {
System.out.println("租房");
System.out.println("收钱");
}
}
// ZuFangProxy.java
// 代理
@Data
public class ZuFangProxy {
private IFangDong fangDong = new FangDongImpl();
public void zufang() {
System.out.println("发布信息");
System.out.println("找人看房");
//
fangDong.zufang();
}
}
// 测试
ZuFangProxy z = new ZuFangProxy();
z.zufang();
动态代理。
// DynamicProxy.java
public class DynamicProxy {
public static void jdk() {
// 主要对有实现接口的实现类进行动态代理的生成
final FangDongImpl fangDong = new FangDongImpl();
// 设置代理
InvocationHandler in = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("发布信息");
System.out.println("找人看房");
fangDong.zufang();
return null;
}
};
// 生成代理类
IFangDong o = (IFangDong) Proxy.newProxyInstance(DynamicProxy.class.getClassLoader(), fangDong.getClass().getInterfaces(), in);
o.zufang();
System.out.println(o.getClass());
}
public static void cglib() {
// 主要应用于没有实现接口的类,进行动态代理的生成
final FangDongImpl fangDong = new FangDongImpl();
Enhancer en = new Enhancer();
en.setSuperclass(FangDongImpl.class);
// 设置代理
en.setCallback(new org.springframework.cglib.proxy.InvocationHandler() {
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
System.out.println("发布信息");
System.out.println("找人看房");
fangDong.zufang();
return null;
}
});
// 生成代理类
IFangDong o = (IFangDong) en.create();
o.zufang();
System.out.println(o.getClass());
}
public static void main(String[] args) {
jdk();
cglib();
}
}
AOP,Aspect Oriented Programming,面向切面编程。
// pom.xml 添加
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.1.16.RELEASE</version>
</dependency>
// MyBefore.java
public class MyBefore implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("这个是aop前置增强");
System.out.println("写日志");
}
}
// spring.xml 部分代码 ,相关的类在上面例子中有
<!-- aop -->
<bean id="fangdong" class="com.baidu.day.text.proxy.FangDongImpl"></bean>
<bean id="zufangproxy" class="com.baidu.day.text.proxy.ZuFangProxy">
<!-- 有属性的引入一定要写 set/get -->
<property name="fangDong" ref="fangdong"></property>
</bean>
<!-- 声明增强类 -->
<bean id="mybefore" class="com.baidu.day.text.advice.MyBefore"></bean>
<aop:config>
// 设置切点。zufang 所有同名方法都会走。
<aop:pointcut id="myPointcut" expression="execution(* zufang(..))"/>
<aop:advisor advice-ref="mybefore" pointcut-ref="myPointcut"></aop:advisor>
</aop:config>
</beans>
// 测试
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
ZuFangProxy proxy = (ZuFangProxy)ac.getBean("zufangproxy");
// class com.baidu.day.text.proxy.ZuFangProxy , proxy说明是代理类
System.out.println(proxy.getClass());
proxy.zufang();
// 打印,前置打印了两次,是因为zufang 方法名匹配到两次的原因
class com.baidu.day.text.proxy.ZuFangProxy$$EnhancerBySpringCGLIB$$e1f1afde
这个是aop前置增强
写日志
发布信息
找人看房
这个是aop前置增强
写日志
租房
收钱